了解 NULL 指针检查时核心转储中的分段错误

Understanding segmentation fault in core dump on NULL pointer check

我很难理解为什么会出现这种分段错误。机器的架构是armv7l.

核心转储:

Dump of assembler code for function DLL_Disconnect:
   0x6cd3a460 <+0>:     15 4b   ldr     r3, [pc, #84]   ; (0x6cd3a4b8 <DLL_Disconnect+88>)
   0x6cd3a462 <+2>:     00 21   movs    r1, #0
   0x6cd3a464 <+4>:     15 4a   ldr     r2, [pc, #84]   ; (0x6cd3a4bc <DLL_Disconnect+92>)
   0x6cd3a466 <+6>:     30 b5   push    {r4, r5, lr}
   0x6cd3a468 <+8>:     83 b0   sub     sp, #12
   0x6cd3a46a <+10>:    7b 44   add     r3, pc
   0x6cd3a46c <+12>:    01 91   str     r1, [sp, #4]
   0x6cd3a46e <+14>:    04 46   mov     r4, r0
   0x6cd3a470 <+16>:    9d 58   ldr     r5, [r3, r2]
=> 0x6cd3a472 <+18>:    28 68   ldr     r0, [r5, #0]
   0x6cd3a474 <+20>:    c0 b1   cbz     r0, 0x6cd3a4a8 <DLL_Disconnect+72>
   0x6cd3a476 <+22>:    21 46   mov     r1, r4
...
   0x6cd3a4b6 <+86>:    00 bf   nop
   0x6cd3a4b8 <+88>:    96 b6 00 00     .word   0x0000b696 <- replaced from objdump, as gdb prints as instruction
   0x6cd3a4bc <+92>:    1c 02 00 00     .word   0x0000021c <- also replaced

寄存器:

r0             0x0                 0
r1             0x0                 0
r2             0x21c               540
r3             0x6cd45b04          1825856260
r4             0x0                 0
r5             0x1dddc             122332
...
sp             0x62afeb40          0x62afeb40
lr             0x72a3091b          1923287323
pc             0x6cd3a472          0x6cd3a472 <DLL_Disconnect+18>
cpsr           0x600c0030          1611399216
fpscr          0x0                 0

当"ldr r0, [r5, #0]" 试图访问r5 指向的内存地址时导致段错误。在 GDB 中,当我尝试在 GDB 中访问它时收到类似的消息:

(gdb) print *$r5
Cannot access memory at address 0x1dddc

但是,所有有问题的寄存器值都是按静态值计算的。所以我不明白内存地址是怎么访问不到的

使用 dlopen 和 dlsym 通过共享库加载和执行源代码:

CClient* gl_pClient = NULL;

extern "C" unsigned long DLL_Disconnect(unsigned long ulHandle)
{
    CProtocol* pCProtocol = NULL;

    unsigned long ulResult = ACTION_INTERNAL_ERROR;

    if (gl_pClient == NULL)
    {
        return ACTION_API_NOT_INITIALIZED;
    }
...

汇编代码使用 dll 重定位解析全局变量 gl_pClient 的地址,这些重定位使用程序计数器相对寻址加载。然后代码从该地址加载并崩溃。看起来重定位已损坏,因此解析的地址无效。

没有复制品就没什么好说的了。

您可能希望 运行 您的程序在 valgrind 下,这可能会报告内存损坏。