zoukankan      html  css  js  c++  java
  • NDK中使用pthread多线程中自己写的一个BUG

      在使用pthread进行NDK中的多线程开发时,自己写了一个BUG,

     1 void *darkGrayThread(void *args)
     2 {
     3     ThreadParam *param = (ThreadParam *)args;
     4     LOG("start%d   end%d   ", param->start, param->end);
     5     int end = param->end;
     6     for(int i = param->start, j = i * 4; i < end; ++i, j+=4)
     7     {
     8         LOG("d1");
     9         param->r[i] = param->rgba[j];
    10         param->g[i] = param->rgba[j + 1];
    11         param->b[i] = param->rgba[j + 2];
    12         LOG("d2  %d    end%d", i, param->end);
    13         param->dark[i] = MINT(param->rgba[j], param->rgba[j + 1], param->rgba[j + 2]);
    14         param->gray[i] = (UCHAR)((param->rgba[j] * 1224 + param->rgba[j + 1] * 2404 +param->rgba[j + 2] * 467) >> 12);
    15         LOG("d3");
    16     }
    17 }

      这个是启动函数,即相当于Java中的Thread的run方法。初一看没啥问题,编译也能过,APP也能跑,但是每次都会crash。我把crash线程的log贴出来如下:

     1 04-16 14:28:31.577 27602 28062 D MyJni   : d2  2087309    end2073600
     2 04-16 14:28:31.637 27602 28062 D MyJni   : d3
     3 04-16 14:28:31.641 27602 28062 D MyJni   : d3
     4 04-16 14:28:31.641 27602 28062 D MyJni   : d1
     5 04-16 14:28:31.641 27602 28062 D MyJni   : d2  2087552    end2073600
     6 04-16 14:28:31.642 27602 28062 D MyJni   : d3
     7 04-16 14:28:31.642 27602 28062 D MyJni   : d1
     8 04-16 14:28:31.642 27602 28062 D MyJni   : d1
     9 04-16 14:28:31.642 27602 28062 D MyJni   : d2  2087567    end2073600
    10 04-16 14:28:31.642 27602 28062 D MyJni   : d3
    11 04-16 14:28:31.642 27602 28062 D MyJni   : d3
    12 04-16 14:28:31.785 27602 28062 D MyJni   : d2  2089380    end2073600
    13 04-16 14:28:31.785 27602 28062 D MyJni   : d3
    14 04-16 14:28:31.785 27602 28062 D MyJni   : d1
    15 04-16 14:28:31.786 27602 28062 D MyJni   : d1
    16 04-16 14:28:31.786 27602 28062 D MyJni   : d2  2089401    end2073600
    17 04-16 14:28:31.786 27602 28062 D MyJni   : d2  2089402    end2073600
    18 04-16 14:28:31.786 27602 28062 D MyJni   : d3
    19 04-16 14:28:31.786 27602 28062 D MyJni   : d2  2089404    end2073600
    20 04-16 14:28:32.339 27602 28062 F libc    : Fatal signal 11 (SIGSEGV), code 1, fault addr 0xc6800000 in tid 28062 (Thread-4)
    21 04-16 14:28:32.339 27602 28062 F libc    : Fatal signal 11 (SIGSEGV), code 1, fault addr 0xc6800000 in tid 28062 (Thread-4)
    22 04-16 14:28:32.340   454   454 W         : debuggerd: handling request: pid=27602 uid=10129 gid=10129 tid=28062
    23 04-16 14:28:32.381 28088 28088 F DEBUG   : pid: 27602, tid: 28062, name: Thread-4  >>> com.willhua.opencvstudy <<<
    24 04-16 14:28:32.381 28088 28088 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc6800000
    25 04-16 14:28:32.381 28088 28088 F DEBUG   :     r0 000000a7  r1 c6600000  r2 cac6ef0e  r3 000000be
    26 04-16 14:28:32.381 28088 28088 F DEBUG   :     r4 caa4ca9c  r5 00200000  r6 00000964  r7 c62038f8
    27 04-16 14:28:32.381 28088 28088 F DEBUG   :     r8 00800002  r9 000001d3  sl cac6ef0e  fp cac6ebe0
    28 04-16 14:28:32.381 28088 28088 F DEBUG   :     ip c7680000  sp c62038e8  lr caa8e93f  pc caa8e99a  cpsr 200f0030
    29 04-16 14:28:32.383 28088 28088 F DEBUG   : 
    30 04-16 14:28:32.383 28088 28088 F DEBUG   : backtrace:
    31 04-16 14:28:32.383 28088 28088 F DEBUG   :     #00 pc 0004099a  /data/app/com.willhua.opencvstudy-2/lib/arm/libOpenCV.so (_Z14darkGrayThreadPv+209)
    32 04-16 14:28:32.383 28088 28088 F DEBUG   :     #01 pc 000475d3  /system/lib/libc.so (_ZL15__pthread_startPv+22)
    33 04-16 14:28:32.383 28088 28088 F DEBUG   :     #02 pc 00019d3d  /system/lib/libc.so (__start_thread+6)

      从log中看出,是内存访问错误,然后使用addr2line工具定位到是上述代码中的第13行。

      再仔细一点可以看到,log中打印的end都比前面的数字小!!!上面不是有for循环的条件语句吗?怎么会出现这种情况!?其中的MINT只是我使用define定义的求三个数中的最小数的宏。

      为了确定问题,我把13写成了

    1  UCHAR uu = MINT(param->rgba[j], param->rgba[j + 1], param->rgba[j + 2]);
    2  param->dark[i] = uu;

      然后根据log分析,还是param->dark[i] = uu; 这行报错。然后我又跑去前面的代码确定给dark分配的内存没有问题。还是没找到原因。

      后面突然发现,写的darkGrayThread没有写返回值!于是赶紧再后面添加一句return (void *)0; 再测试,发现没问题,原因就是这个了。

      为了知道原因,我在没有写return的版本的最后添加LOG("endend"); 发现每次都会有数量不等的endend日志打印出来。这说明for的条件语句还是有退出循环的作用的。

      要想继续分析,可能需要对比有没有return的两个版本的汇编代码,来比较一下有没有return他们翻译成汇编的区别,待后续分析。

      这个问题的收获就是:写启动程序一定记得有return语句,即使你的return值没有用!

  • 相关阅读:
    LeetCode 102. 二叉树的层次遍历
    Java | JDK8下的ConcurrentHashMap#get
    Java | JDK8下的ConcurrentHashMap#putValue
    CCF | 小中大
    Jvm | 《深入理解Java虚拟机》读书笔记 |
    Jvm | 《深入理解Java虚拟机》读书笔记 | 线程安全与锁优化
    3. 帧定格和导出单帧
    2. premiere 项目管理
    1.后期特效合成AE概述&&工作流程&&磁盘缓存清理
    贷款减值准备和折现回拨
  • 原文地址:https://www.cnblogs.com/willhua/p/6718884.html
Copyright © 2011-2022 走看看