了解 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
下,这可能会报告内存损坏。
我很难理解为什么会出现这种分段错误。机器的架构是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
下,这可能会报告内存损坏。