GCDFetchFeed icon indicating copy to clipboard operation
GCDFetchFeed copied to clipboard

SMCallTrace 调用栈顺序问题

Open chipengliu opened this issue 6 years ago • 1 comments

问题1、拼接调用栈路径path顺序不正确

- (void)viewDidLoad {
    [super viewDidLoad];
    UIWebView *webview = [[UIWebView alloc] init];
    [self.view addSubview:webview];
    NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];
    NSURLRequest *req = [[NSURLRequest alloc] initWithURL:url];
    [webview loadRequest:req];
    webview.frame = self.view.bounds;

    [self testMethod1];
}

- (void)testMethod1 {
    NSString *imgName = [NSString stringWithFormat:@"guide_1"];
    NSString *path = [[NSBundle mainBundle] pathForResource:imgName ofType:@"png"];
    UIImage *image = [UIImage imageWithContentsOfFile:path];
    self.view.backgroundColor = [UIColor colorWithPatternImage:image];
    
    [self testMethod2];
}

- (void)testMethod2 {
    [self testMethod3];
}

- (void)testMethod3 {
    NSString *imgName = [NSString stringWithFormat:@"guide_3"];
    NSString *path = [[NSBundle mainBundle] pathForResource:imgName ofType:@"png"];
    UIImage *image = [UIImage imageWithContentsOfFile:path];
    self.view.backgroundColor = [UIColor colorWithPatternImage:image];
    
    UIGraphicsBeginImageContext(self.view.frame.size);
    [image drawInRect:self.view.bounds];
    image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    self.view.backgroundColor = [UIColor colorWithPatternImage:image];
}

这里UIWebView某些回调方法是通过异步回到主线程执行,看起来多线程打印的调用栈路径是错误的,打印出来的信息是:

 0| +[UIWebView alloc]
 path[UIWebView alloc]
 0| -[UIWebView init]
 path[UIWebView init]
 0| -[ViewController testMethod1]
 path[ViewController testMethod1]
 1|   -[ViewController testMethod2]
 path[ViewController testMethod1] - [ViewController testMethod2]
 2|     -[ViewController testMethod3]
 path[ViewController testMethod1] - [ViewController testMethod2] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[ViewController testMethod1] - [ViewController testMethod2] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   +[UIImage imageWithContentsOfFile:]
 path[ViewController testMethod1] - [UIImage imageWithContentsOfFile:]
 0| -[_WebSafeForwarder webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 path[_WebSafeForwarder webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 1|   -[UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 path[_WebSafeForwarder webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   -[ViewController testMethod2]
 path[_WebSafeForwarder webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [ViewController testMethod2]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [ViewController testMethod2] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [ViewController testMethod2] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   +[UIImage imageWithContentsOfFile:]
 path[_WebSafeForwarder webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [UIImage imageWithContentsOfFile:]
 0| -[_WebSafeForwarder webView:decidePolicyForMIMEType:request:frame:decisionListener:]
 path[_WebSafeForwarder webView:decidePolicyForMIMEType:request:frame:decisionListener:]
 1|   -[UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:]
 path[_WebSafeForwarder webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   -[UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 path[_WebSafeForwarder webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   -[ViewController testMethod2]
 path[_WebSafeForwarder webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [ViewController testMethod2]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [ViewController testMethod2] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [ViewController testMethod2] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   +[UIImage imageWithContentsOfFile:]
 path[_WebSafeForwarder webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [UIImage imageWithContentsOfFile:]
 0| -[_WebSafeForwarder webView:didCommitLoadForFrame:]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:]
 1|   -[UIWebBrowserView webView:didCommitLoadForFrame:]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:] - [UIWebBrowserView webView:didCommitLoadForFrame:]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:] - [UIWebBrowserView webView:didCommitLoadForFrame:] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:] - [UIWebBrowserView webView:didCommitLoadForFrame:] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   -[UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   -[UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   -[ViewController testMethod2]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:] - [ViewController testMethod2]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:] - [ViewController testMethod2] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:] - [ViewController testMethod2] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   +[UIImage imageWithContentsOfFile:]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:] - [UIImage imageWithContentsOfFile:]
 0| -[_WebSafeForwarder webView:didFinishLoadForFrame:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:]
 1|   -[UIWebBrowserView webView:didFinishLoadForFrame:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebBrowserView webView:didFinishLoadForFrame:]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebBrowserView webView:didFinishLoadForFrame:] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebBrowserView webView:didFinishLoadForFrame:] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   -[UIWebBrowserView webView:didCommitLoadForFrame:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebBrowserView webView:didCommitLoadForFrame:]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebBrowserView webView:didCommitLoadForFrame:] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebBrowserView webView:didCommitLoadForFrame:] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   -[UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   -[UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   -[ViewController testMethod2]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [ViewController testMethod2]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [ViewController testMethod2] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [ViewController testMethod2] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   +[UIImage imageWithContentsOfFile:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIImage imageWithContentsOfFile:]
 0| -[_WebSafeForwarder webView:didFinishLoadForFrame:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:]
 1|   -[UIWebViewWebViewDelegate webView:didFinishLoadForFrame:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:didFinishLoadForFrame:]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:didFinishLoadForFrame:] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:didFinishLoadForFrame:] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   -[UIWebBrowserView webView:didFinishLoadForFrame:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebBrowserView webView:didFinishLoadForFrame:]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebBrowserView webView:didFinishLoadForFrame:] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebBrowserView webView:didFinishLoadForFrame:] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   -[UIWebBrowserView webView:didCommitLoadForFrame:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebBrowserView webView:didCommitLoadForFrame:]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebBrowserView webView:didCommitLoadForFrame:] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebBrowserView webView:didCommitLoadForFrame:] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   -[UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   -[UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   -[ViewController testMethod2]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [ViewController testMethod2]
 2|     -[ViewController testMethod3]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [ViewController testMethod2] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [ViewController testMethod2] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   +[UIImage imageWithContentsOfFile:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIImage imageWithContentsOfFile:]

如果在loadRecords方法第二层循环加上break,看起才是正常的

    for (NSUInteger i = 0; i < count; i++) {
        SMCallTraceTimeCostModel *model = arr[i];
        if (model.callDepth > 0) {
            [arr removeObjectAtIndex:i];
            //Todo:不需要循环,直接设置下一个,然后判断好边界就行
            for (NSUInteger j = i; j < count - 1; j++) {
                //下一个深度小的话就开始将后面的递归的往 sub array 里添加
                if (arr[j].callDepth + 1 == model.callDepth) {
                    NSMutableArray *sub = (NSMutableArray *)arr[j].subCosts;
                    if (!sub) {
                        sub = [NSMutableArray new];
                        arr[j].subCosts = sub;
                    }
                    [sub insertObject:model atIndex:0];
                    break;//->fix 找到父节点结束遍历
                }
            }
            i--;
            count--;
        }
    }

加了break 之后输出

 0| +[UIWebView alloc]
 path[UIWebView alloc]
 0| -[UIWebView init]
 path[UIWebView init]
 0| -[ViewController testMethod1]
 path[ViewController testMethod1]
 1|   -[ViewController testMethod2]
 path[ViewController testMethod1] - [ViewController testMethod2]
 2|     -[ViewController testMethod3]
 path[ViewController testMethod1] - [ViewController testMethod2] - [ViewController testMethod3]
 3|       -[UIImage drawInRect:]
 path[ViewController testMethod1] - [ViewController testMethod2] - [ViewController testMethod3] - [UIImage drawInRect:]
 1|   +[UIImage imageWithContentsOfFile:]
 path[ViewController testMethod1] - [UIImage imageWithContentsOfFile:]
 0| -[_WebSafeForwarder webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 path[_WebSafeForwarder webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 1|   -[UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 path[_WebSafeForwarder webView:decidePolicyForNavigationAction:request:frame:decisionListener:] - [UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
 0| -[_WebSafeForwarder webView:decidePolicyForMIMEType:request:frame:decisionListener:]
 path[_WebSafeForwarder webView:decidePolicyForMIMEType:request:frame:decisionListener:]
 1|   -[UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:]
 path[_WebSafeForwarder webView:decidePolicyForMIMEType:request:frame:decisionListener:] - [UIWebViewWebViewDelegate webView:decidePolicyForMIMEType:request:frame:decisionListener:]
 0| -[_WebSafeForwarder webView:didCommitLoadForFrame:]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:]
 1|   -[UIWebBrowserView webView:didCommitLoadForFrame:]
 path[_WebSafeForwarder webView:didCommitLoadForFrame:] - [UIWebBrowserView webView:didCommitLoadForFrame:]
 0| -[_WebSafeForwarder webView:didFinishLoadForFrame:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:]
 1|   -[UIWebViewWebViewDelegate webView:didFinishLoadForFrame:]
 path[_WebSafeForwarder webView:didFinishLoadForFrame:] - [UIWebViewWebViewDelegate webView:didFinishLoadForFrame:]

问题2、debug由于hook objc_msgSend 导致 堆栈信息不全

在同一行代码用bt命令打印堆栈 hook前 hook前

hook后 hook后


问题3、无法检测viewDidLoad, viewWillAppear 等一些UIKit的方法

目前发现 UIViewController、UIResponder 等一些方法是无法记录的

chipengliu avatar Aug 23 '19 08:08 chipengliu

搭个车... 想邀请Repo作者来w3c.group创建项目的对应小组。w3c.group是类似知识星球的社群工具,小组可设置为付费且有赞助功能,同时也是一个区块链主导的创作者社区。这是相关介绍: http://t.cn/Ai1vLcCU http://t.cn/Ai1vLcCG http://t.cn/Ai1vLcCA

isdotjim avatar Oct 24 '19 04:10 isdotjim

问题一:路径问题应该是调用链路错误导致,可以参考下面的提交 https://github.com/ming1016/GCDFetchFeed/pull/30 问题二:不太好确认是什么关系,但是我理解不影响使用,毕竟这个工具是用于开发定位问题,而不是代入线上;

erduoniba avatar Dec 20 '23 04:12 erduoniba