gpt4 book ai didi

使用 android ndk 进行内存损坏调试

转载 作者:行者123 更新时间:2023-12-02 22:02:59 26 4
gpt4 key购买 nike

当 void 函数返回到其调用者时,我的 Android 应用程序的 native 部分出现了段错误。为了更好地可视化,我在被调用者函数的末尾放置了一条日志语句,并在调用者函数中放置了一条日志语句,紧接在调用被调用者之后(对不起,双关语)。在 logcat 中,打印第一条消息,但不打印第二条消息(应用程序崩溃)。

考虑到可能的内存损坏,我决定激活 malloc 调试(在 adb shell 中给出“setprop libc.debug.malloc 10”)。然后,我在被调用函数末尾的日志消息之后立即在 logcat 中得到此信息:

D/MyApp - NativeSide(12778):  I am the callee function and I am about to return!
E/libc (12778): *** FREE CHECK: buffer 0x82869900 corrupted 16 bytes before allocation
E/libc (12778): call stack:
E/libc (12778): 0: 8000e3ea
E/libc (12778): 1: 8000e49c
E/libc (12778): 2: 8000e4e2
E/libc (12778): 3: 8000e540
E/libc (12778): 4: afd14ccc
E/libc (12778): 5: 81258188
E/libc (12778): 6: 81258188
E/libc (12778): 7: 81258188
E/libc (12778): 8: 81258188
E/libc (12778): 9: 81258188
E/libc (12778): 10: 81258188
E/libc (12778): 11: 81258188
E/libc (12778): 12: 81258188
E/libc (12778): 13: 81258188
E/libc (12778): 14: 81258188
E/libc (12778): 15: 81258188
E/libc (12778): 16: 81258188
E/libc (12778): 17: 81258188
E/libc (12778): 18: 81258188
E/libc (12778): 19: 81258188

我找不到任何有关如何破译此输出的信息。每行显示的数字在每次应用程序启动时都会发生变化。我希望有一种方法可以使用这些信息作为腐败发生位置的线索,因为我无法从代码中找到它。我还尝试使用“-fstack-check 标志构建 native 库,但我无法说我是否在日志中获得了更多信息(似乎没有,但我可能错过了它们),或者我是否需要做其他事情来获取它们。

此外,这是堆栈转储,位于“FREE CHECK:”消息之后。

I/DEBUG   (12311): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG (12311): Build fingerprint: 'google/soju/crespo:2.3/GRH55/79397:user/release-keys'
I/DEBUG (12311): pid: 12778, tid: 12907 >>> com.ntrack.tuner <<<
I/DEBUG (12311): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad
I/DEBUG (12311): r0 deadbaad r1 45ea374c r2 00000027 r3 00000000
I/DEBUG (12311): r4 00000080 r5 45ea374c r6 8003422e r7 45ea37b4
I/DEBUG (12311): r8 45da4000 r9 a811eca5 10 00100000 fp 00000001
I/DEBUG (12311): ip ffffffff sp 45ea3738 lr 8000f623 pc 8000f650 cpsr 20000030
I/DEBUG (12311): d0 3f9664f48406d639 d1 3f8226e3e96e8495
I/DEBUG (12311): d2 3faba1ba1bb34201 d3 0000000000000000
I/DEBUG (12311): d4 3d7943379e56fd24 d5 3d8f940585cd5f95
I/DEBUG (12311): d6 3f2cf2145b888497 d7 3f2cf214636d85f8
I/DEBUG (12311): d8 0000000000000000 d9 0000000000000000
I/DEBUG (12311): d10 0000000000000000 d11 0000000000000000
I/DEBUG (12311): d12 0000000000000000 d13 0000000000000000
I/DEBUG (12311): d14 0000000000000000 d15 0000000000000000
I/DEBUG (12311): scr 20000010
I/DEBUG (12311):

任何关于要检查的典型事项的建议或只是使用 malloc 调试信息的方法都会有很大帮助,谢谢!

最佳答案

malloc 调试属性可能在您分配的区域之前和之后设置一些魔数(Magic Number)。然后,在释放时,它会检查这些区域以确保魔数(Magic Number)仍然存在。

例如,如果您分配 1024 字节:

char * p = malloc(1024);

malloc 调试代码实际上会分配您请求的 1024 个字节,再加上一些额外的字节:

[ 32 bytes ---- | -------- 1024 bytes ------| ---- 32 bytes ]
^ 0xc0000000 ^ 0xc0000020

然后,库会将一个神奇值写入这 32 个字节:

[ 32 bytes ---- | -------- 1024 bytes ------| ---- 32 bytes ]
[ 0xdeadd00d | | 0xdeadd00d ]
^ 0xc0000000 ^ 0xc0000020

图书馆将返回 0xc0000020进入p在内部它会保存 0xc0000000 、尺寸等然后,您的函数会以某种方式使用分配的区域:

memset(p, 0, 1025);

请注意,此行复制了超过 1024 个字节。这会将 0 写入最后 32 字节魔术区域(注意最后 32 字节中的 0 ,它应该是 0xdeadd00d ):

[ 32 bytes ---- | -------- 1024 bytes ------| ---- 32 bytes ]
[ 0xdeadd00d | 000... ...00 | 0x0eadd00d ]
^ 0xc0000000 ^ 0xc0000020 (address)

当你的函数调用 free 时:

free(p);

然后,库将检查以确保第一个和最后 32 个字节仍然是 0xdeadd00d 。由于您的函数覆盖了最后 32 个字节,因此它会打印您发布的错误。

这只是 malloc 调试检查如何工作的一个示例。如果您想确切了解 malloc 调试检查的内容及其工作原理,请转至 bionic Android 源代码目录并搜索您设置的属性,libc.debug.malloc

检查您的代码,了解如何在被调用函数中使用分配的内存。您可能正在向您分配的区域之外的区域写入数据。

关于使用 android ndk 进行内存损坏调试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11333449/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com