A bug self-written by NDK using pthread in multiple threads, ndkpthread
When using pthread for multi-thread development in NDK, I wrote a 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 }
This is the startup function, which is equivalent to the Thread run method in Java. At the first day, there was no problem. The APP can be compiled and run, but crash is used every time. I posted the crash thread log as follows:
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 end207360010 04-16 14:28:31.642 27602 28062 D MyJni : d311 04-16 14:28:31.642 27602 28062 D MyJni : d312 04-16 14:28:31.785 27602 28062 D MyJni : d2 2089380 end207360013 04-16 14:28:31.785 27602 28062 D MyJni : d314 04-16 14:28:31.785 27602 28062 D MyJni : d115 04-16 14:28:31.786 27602 28062 D MyJni : d116 04-16 14:28:31.786 27602 28062 D MyJni : d2 2089401 end207360017 04-16 14:28:31.786 27602 28062 D MyJni : d2 2089402 end207360018 04-16 14:28:31.786 27602 28062 D MyJni : d319 04-16 14:28:31.786 27602 28062 D MyJni : d2 2089404 end207360020 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=2806223 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 0xc680000025 04-16 14:28:32.381 28088 28088 F DEBUG : r0 000000a7 r1 c6600000 r2 cac6ef0e r3 000000be26 04-16 14:28:32.381 28088 28088 F DEBUG : r4 caa4ca9c r5 00200000 r6 00000964 r7 c62038f827 04-16 14:28:32.381 28088 28088 F DEBUG : r8 00800002 r9 000001d3 sl cac6ef0e fp cac6ebe028 04-16 14:28:32.381 28088 28088 F DEBUG : ip c7680000 sp c62038e8 lr caa8e93f pc caa8e99a cpsr 200f003029 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)
From the log, we can see that it is a memory access error, and then use the addr2line tool to locate the 13th rows in the above Code.
A closer look, we can see that the end printed in the log is smaller than the previous number !!! Isn't there a conditional statement for the for Loop above? How can this happen !? The MINT is just the macro that I use the define definition to calculate the minimum number of three numbers.
To confirm the problem, I wrote 13
1 UCHAR uu = MINT(param->rgba[j], param->rgba[j + 1], param->rgba[j + 2]);2 param->dark[i] = uu;
Then, based on log analysis, the following error occurs: param-> dark [I] = uu. Then I ran to the previous code to determine that there was no problem with the memory allocated to dark. Still cannot find the reason.
Later, we suddenly found that the written darkGrayThread did not return the value! Then, add a return (void *) 0 statement later. Then test the code and find that there is no problem. This is the reason.
To understand the cause, I added LOG ("endend") at the end of the version without the return statement; I found that each time a number of endend logs are printed. This shows that the for Condition Statement can exit the loop.
To continue the analysis, you may need to compare the two versions of the assembly code with or without return to compare the differences between the two versions of the assembly code with or without return, which will be analyzed later.
The result of this problem is: Write the Startup Program and remember to have a return statement, even if your return value is useless!