当前位置:   article > 正文

malloc debug 内存泄露案例分析_malloc_debug

malloc_debug

目录

 

前言

阅读/bionic/libc/malloc_debug/README.md

native_heapdump_viewer.py使用

测试代码

测试代码log分析

案例

自动dump脚本(malloc_debug.sh)

注意事项


前言

环境:Android10

目的:调试native 进程内存泄露,内存分配,踩内存相关问题。

阅读/bionic/libc/malloc_debug/README.md

Malloc Debug, 如果启用了malloc debug 功能,则将替换如下函数,而使用malloc_debug的函数

  1. malloc
  2. free
  3. calloc
  4. realloc
  5. posix_memalign
  6. memalign
  7. aligned_alloc
  8. malloc_usable_size

 

Controlling Malloc Debug Behavior

  • front_guard[=SIZE_BYTES]

每次调用malloc,都在分配的区域之前填充SIZE_BYTES,填充内容为0xaa

例子:setprop libc.debug.malloc.options front_guard=16

  1. ptr = (char*)malloc(1 * 1024 * 1024);
  2. memset(ptr, 0, 1 * 1024 * 1024);
  3. printf("*(ptr - 16) = %d\n", *(ptr - 16)); // 这里打印170 (0XAA)
  4. *(ptr - 16) = 0xee; //这里会出现memory corruption occuring
  5. free(ptr) // malloc debug 会在free的时候检测那些出现内存损坏的地方
front_guard
front guard

 

 

 

 

因为该程序出现了内存踩踏,所以会打印如下log

front_guiard_err

  • rear_guard[=SIZE_BYTES]

每次调用malloc,都在指向内存的最后填充SIZE_BYTES,填充内容为0xbb

rear_guard

举例:setprop libc.debug.malloc.options rear_guard=16

  1. ptr = (char*)malloc(1 * 1024 * 1024);
  2. memset(ptr, 0, 1 * 1024 * 1024);
  3. printf("*(ptr - 16) = %d\n", *(ptr - 16)); // 这里打印187 (0Xbb)
  4. *(ptr + 1*1024*1024) = 0xee; //这里会出现memory corruption occuring
  5. free(ptr) // malloc debug 会在free的时候检测出现内存损坏的地方

rear_guard_err

  • guard[=SIZE_BYTES]

这个选项包含了 front_guard 和 rear_guard。在指向内存的前后连续SIZE_BYTES 分别填充0xaa 和 0xbb

guard

  • backtrace[=MAX_FRAMES]

MAX_FRAMES 最大值256 默认值16

每次在调用malloc时,malloc debug 都会记录malloc的调用栈(trace),栈的最大深度为MAX_FRAMES,MAX_FRAMES 越大,对malloc的性能影响越大。

当进程收到信号(SIGRTMAX - 17)Android通常该信号值为47时,会触发malloc debug 的dump heap trace功能。默认dump路径在/data/local/tmp/ backtrace_heap.PID.txt。

给进程发信号通过kill -s 47 PID,进程收到信号后并不会马上dump backtrace,二是会等到下次调用malloc 或者 free时才会触发。所以如果发送信号后没有产生trace文件,请继续针对调试的进程做测试。

举例:

setprop libc.debug.malloc.options backtrace=5

得到的dump文件为 $pid.txt 结尾

  • backtrace_enable_on_signal[=MAX_FRAMES]

使能这个选项,通过给进程发送信号 45,可以动态开启和关闭backtrace 功能。

  • backtrace_dump_on_exit

进程退出后自动dump trace 文件,得到的dump文件为 $pid.exit.txt 结尾

  • backtrace_dump_prefix

trace dump的路径,如果需要放置其他目录,如/sdcard/heap, 则dump的文件路径为/sdcard/heap.$PID.txt

  • leak_track

程序结束后,如果有未free的指针,logcat中会打印出来

  1. 12-19 14:54:32.583 7971 7971 E malloc_debug: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
  2. 12-19 14:55:02.585 7971 7971 E malloc_debug: +++ androidtest leaked block of size 3072 at 0x736e78f030 (leak 1 of 7) //内存泄露的log,直到程序退出未释放的内存
  3. 12-19 14:55:02.585 7971 7971 E malloc_debug: Backtrace at time of allocation:
  4. 12-19 14:55:02.585 7971 7971 E malloc_debug: #00 pc 00000000000152b0 /apex/com.android.runtime/lib64/libc_malloc_debug.so (debug_calloc+432)
  5. 12-19 14:55:02.585 7971 7971 E malloc_debug: #01 pc 000000000000114c /system/bin/androidtest // 通过 addr2line -e symbols/system/bin/androidtest 000000000000114c 可以得到具体是哪一个指针未释放内存。
  6. 12-19 14:55:02.585 7971 7971 E malloc_debug: #02 pc 000000000007d86c /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+108)
  7. 12-19 14:55:02.585 7971 7971 E malloc_debug: #03 pc 000000000000104c /system/bin/androidtest
  8. 12-19 14:55:02.585 7971 7971 E malloc_debug: #04 pc 00000000000533f4 /apex/com.android.runtime/bin/linker64
  9. 12-19 14:55:02.585 7971 7971 E malloc_debug: +++ androidtest leaked block of size 88 at 0x736e631030 (leak 2 of 7)
  • record_allocs[=TOTAL_ENTRIES],该选项很占内存,建议不开启

对进程中使用malloc, calloc, realloc 的地方进行记录,打印的格式如下

Threadid:     action   pointer   size

471: malloc 0x72e00330c0 6

471: realloc 0x72e0005220 0x72e00330c0 12

471: free 0x72e012fcc0

471: free 0x72e0005220

471: malloc 0x72e01ade40 56

471: malloc 0x72e00330c0 6    

注意,最大记录8,000,000 条

  • verbose

打开malloc debug 更多log,类似

  1. 08-16 15:54:16.060 26947 26947 I libc    : /system/bin/app_process64: malloc debug enabled
  2. 09-10 01:03:50.070   557   557 I malloc_debug: /system/bin/audioserver: Run: 'kill -47 557' to dump the backtrace.

 

native_heapdump_viewer.py使用

该工具可以将dump trace文件通过符号表得到当前未释放内存的指针在代码中的行号。准确性依赖trace保存栈的最大深度。所以最好有两份该文件,分别是不同占用内存时dump 得到的。对比查看哪个指针嫌疑最大,缩小范围继续排查。

例子:

native_heapdump_viewer.py backtrace_heap.7971.exit.txt --symbols ~/Download/symbols  --reverse > backtrace_heap.7971.exit.txt.heapout

 

测试代码

  1. #include <string.h>
  2. #include <cutils/log.h>
  3. #include <stdlib.h>
  4. #include <sys/time.h>
  5. #include <unistd.h>
  6. #include <time.h>
  7. #include <vector>
  8. class Foo {
  9. public:
  10. Foo() {
  11. arry = new char[1 * 1024 * 1024];
  12. };
  13. ~Foo() {
  14. delete[] arry;
  15. };
  16. char* arry;
  17. };
  18. using namespace std;
  19. int main(int argc, char* argv[])
  20. {
  21. char *ptr = NULL, *ptr1 = NULL, *ptr2 = NULL, *ptr3 = NULL;
  22. Foo foo;
  23. printf("my pid is: %d\n", getpid());
  24. ptr = (char*)malloc(1 * 1024 * 1024);
  25. if (!ptr) {
  26. return -1;
  27. }
  28. printf("ptr = (char*)malloc(1 * 1024 * 1024): %p\n", ptr);
  29. memset(ptr, 0, 1 * 1024 * 1024);
  30. // front_guard test
  31. // setprop libc.debug.malloc.options front_guard=16
  32. // ptr 指向的内存之前的连续16字节被填充为0xaa,修改该值
  33. printf("*(ptr - 16) = %d\n", *(ptr - 16));
  34. *(ptr - 16) = 0xee;
  35. // rear_guard test
  36. // setprop libc.debug.malloc.options rear_guard=16
  37. // ptr 指向的内存之后的连续16字节被填充为0xbb,修改该值
  38. printf("*(ptr + 1 * 1024 * 1024) = %d\n", *(ptr + 1 * 1024 * 1024));
  39. *(ptr + 1 * 1024 * 1024) = 0xee;
  40. printf("arry = new char[1 * 1024 * 1024]: %p\n", foo.arry);
  41. // free 操作会触发一个踩内存的log
  42. free(ptr);
  43. printf("memory corruption occuring, please check log \n");
  44. // 接下来为了验证 backtrace选项,发送信号之后需要有malloc/free操作才能触发dump,所以休眠30s,再次调用malloc
  45. printf("sleep 30s, please send signal 47 (kill -s 47 mypid) to me, in order to trigger dump trace\n");
  46. sleep(30);
  47. ptr1 = (char*)malloc(1 * 1024);
  48. if (ptr1) {
  49. printf("ptr1 = (char*)malloc(1 * 1024 * 1024): %p\n", ptr1);
  50. }
  51. printf("dump trace success, please check\n\n");
  52. ptr3 = (char*)calloc(3, 1 * 1024); // 该内存程序结束时未释放,会在 dumptrace解析文件中打印出该行号
  53. if (ptr3) {
  54. printf("ptr3 = (char*)malloc(3 * 1024 * 1024): %p\n", ptr3);
  55. }
  56. printf("the programe will exit after 10s, and auto dump tracing if you enable backtrace_dump_on_exit option\n");
  57. free(ptr1);
  58. free(ptr2);
  59. vector<char*> vec(3);
  60. vec[0] = new char[5]; // 该内存程序结束时未释放,会在 dumptrace解析文件中打印出该行号
  61. vec[1] = new char[6]; // 该内存程序结束时未释放,会在 dumptrace解析文件中打印出该行号
  62. vec[2] = new char[7]; // 该内存程序结束时未释放,会在 dumptrace解析文件中打印出该行号
  63. memcpy(vec[0], "111", 3);
  64. memcpy(vec[1], "222", 3);
  65. memcpy(vec[2], "333", 3);
  66. printf("front: %p, begin: %p, size %lu\n", vec.front(), *(vec.begin()), vec.size());
  67. // 只进行clear 并没有释放内存,仍然会打印
  68. vec.clear();
  69. //如果需要释放内存,请使用如下代码,否则vec内存不会释放
  70. //for (vector<char *>::iterator it = vec.begin(); it != vec.end(); it++) {
  71. // if (NULL != *it)
  72. // {
  73. // delete *it;
  74. // *it = NULL;
  75. // }
  76. //}
  77. // ptr3 和 vec 内存都没有是否. 如果使能了leak_track,那么将打印内存泄露log
  78. printf("the programe exit, ptr3 is not free, logcat will printf memory leak log\n");
  79. return 0;
  80. }

测试代码log分析

  1. adb shell logcat -s malloc_debug
  2. --------- beginning of system
  3. 12-19 14:54:32.582 7971 7971 E malloc_debug: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
  4. 12-19 14:54:32.582 7971 7971 E malloc_debug: +++ ALLOCATION 0x736ddf4630 SIZE 1048576 HAS A CORRUPTED FRONT GUARD //打开选项front_guard[] 或者 guard=[], 打印的内存踩踏log
  5. 12-19 14:54:32.582 7971 7971 E malloc_debug: allocation[-16] = 0xee (expected 0xaa)
  6. 12-19 14:54:32.582 7971 7971 E malloc_debug: Backtrace at time of failure:
  7. 12-19 14:54:32.582 7971 7971 E malloc_debug: #00 pc 0000000000014940 /apex/com.android.runtime/lib64/libc_malloc_debug.so
  8. 12-19 14:54:32.582 7971 7971 E malloc_debug: #01 pc 0000000000014800 /apex/com.android.runtime/lib64/libc_malloc_debug.so (debug_free+144)
  9. 12-19 14:54:32.582 7971 7971 E malloc_debug: #02 pc 00000000000010f4 /system/bin/androidtest
  10. 12-19 14:54:32.582 7971 7971 E malloc_debug: #03 pc 000000000007d86c /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+108)
  11. 12-19 14:54:32.582 7971 7971 E malloc_debug: #04 pc 000000000000104c /system/bin/androidtest
  12. 12-19 14:54:32.582 7971 7971 E malloc_debug: #05 pc 00000000000533f4 /apex/com.android.runtime/bin/linker64
  13. 12-19 14:54:32.583 7971 7971 E malloc_debug: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
  14. 12-19 14:54:32.583 7971 7971 E malloc_debug: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
  15. 12-19 14:54:32.583 7971 7971 E malloc_debug: +++ ALLOCATION 0x736ddf4630 SIZE 1048576 HAS A CORRUPTED REAR GUARD //打开选项rear_guard[] 或者 guard=[], 打印的内存踩踏log
  16. 12-19 14:54:32.583 7971 7971 E malloc_debug: allocation[1048576] = 0xee (expected 0xbb)
  17. 12-19 14:54:32.583 7971 7971 E malloc_debug: Backtrace at time of failure:
  18. 12-19 14:54:32.583 7971 7971 E malloc_debug: #00 pc 000000000001496c /apex/com.android.runtime/lib64/libc_malloc_debug.so
  19. 12-19 14:54:32.583 7971 7971 E malloc_debug: #01 pc 0000000000014800 /apex/com.android.runtime/lib64/libc_malloc_debug.so (debug_free+144)
  20. 12-19 14:54:32.583 7971 7971 E malloc_debug: #02 pc 00000000000010f4 /system/bin/androidtest
  21. 12-19 14:54:32.583 7971 7971 E malloc_debug: #03 pc 000000000007d86c /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+108)
  22. 12-19 14:54:32.583 7971 7971 E malloc_debug: #04 pc 000000000000104c /system/bin/androidtest
  23. 12-19 14:54:32.583 7971 7971 E malloc_debug: #05 pc 00000000000533f4 /apex/com.android.runtime/bin/linker64
  24. 12-19 14:54:32.583 7971 7971 E malloc_debug: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
  25. 12-19 14:55:02.585 7971 7971 E malloc_debug: +++ androidtest leaked block of size 3072 at 0x736e78f030 (leak 1 of 7) //内存泄露的log,直到程序退出未释放的内存
  26. 12-19 14:55:02.585 7971 7971 E malloc_debug: Backtrace at time of allocation:
  27. 12-19 14:55:02.585 7971 7971 E malloc_debug: #00 pc 00000000000152b0 /apex/com.android.runtime/lib64/libc_malloc_debug.so (debug_calloc+432)
  28. 12-19 14:55:02.585 7971 7971 E malloc_debug: #01 pc 000000000000114c /system/bin/androidtest // 通过 addr2line -e symbols/system/bin/androidtest 000000000000114c 可以得到具体是哪一个指针未释放内存。
  29. 12-19 14:55:02.585 7971 7971 E malloc_debug: #02 pc 000000000007d86c /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+108)
  30. 12-19 14:55:02.585 7971 7971 E malloc_debug: #03 pc 000000000000104c /system/bin/androidtest
  31. 12-19 14:55:02.585 7971 7971 E malloc_debug: #04 pc 00000000000533f4 /apex/com.android.runtime/bin/linker64
  32. 12-19 14:55:02.588 7971 7971 E malloc_debug: +++ androidtest leaked block of size 7 at 0x736e626a60 (leak 5 of 7)
  33. 12-19 14:55:02.588 7971 7971 E malloc_debug: Backtrace at time of allocation:
  34. 12-19 14:55:02.588 7971 7971 E malloc_debug: #00 pc 000000000001470c /apex/com.android.runtime/lib64/libc_malloc_debug.so
  35. 12-19 14:55:02.588 7971 7971 E malloc_debug: #01 pc 0000000000014534 /apex/com.android.runtime/lib64/libc_malloc_debug.so (debug_malloc+108)
  36. 12-19 14:55:02.588 7971 7971 E malloc_debug: #02 pc 00000000000675c0 /system/lib64/libc++.so (operator new(unsigned long)+32)
  37. 12-19 14:55:02.588 7971 7971 E malloc_debug: #03 pc 00000000000011a8 /system/bin/androidtest // 通过addr2line 得到未释放内存的指针
  38. 12-19 14:55:02.588 7971 7971 E malloc_debug: #04 pc 000000000007d86c /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+108)
  39. 12-19 14:55:02.588 7971 7971 E malloc_debug: #05 pc 000000000000104c /system/bin/androidtest
  40. 12-19 14:55:02.588 7971 7971 E malloc_debug: #06 pc 00000000000533f4 /apex/com.android.runtime/bin/linker64
  41. 12-19 14:55:02.588 7971 7971 E malloc_debug: +++ androidtest leaked block of size 6 at 0x736e626a10 (leak 6 of 7)
  42. 12-19 14:55:02.588 7971 7971 E malloc_debug: Backtrace at time of allocation:
  43. 12-19 14:55:02.588 7971 7971 E malloc_debug: #00 pc 000000000001470c /apex/com.android.runtime/lib64/libc_malloc_debug.so
  44. 12-19 14:55:02.588 7971 7971 E malloc_debug: #01 pc 0000000000014534 /apex/com.android.runtime/lib64/libc_malloc_debug.so (debug_malloc+108)
  45. 12-19 14:55:02.588 7971 7971 E malloc_debug: #02 pc 00000000000675c0 /system/lib64/libc++.so (operator new(unsigned long)+32)
  46. 12-19 14:55:02.588 7971 7971 E malloc_debug: #03 pc 0000000000001198 /system/bin/androidtest // 通过addr2line 得到未释放内存的指针
  47. 12-19 14:55:02.588 7971 7971 E malloc_debug: #04 pc 000000000007d86c /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+108)
  48. 12-19 14:55:02.588 7971 7971 E malloc_debug: #05 pc 000000000000104c /system/bin/androidtest
  49. 12-19 14:55:02.588 7971 7971 E malloc_debug: #06 pc 00000000000533f4 /apex/com.android.runtime/bin/linker64
  50. 12-19 14:55:02.589 7971 7971 E malloc_debug: +++ androidtest leaked block of size 5 at 0x736e6269c0 (leak 7 of 7)
  51. 12-19 14:55:02.589 7971 7971 E malloc_debug: Backtrace at time of allocation:
  52. 12-19 14:55:02.589 7971 7971 E malloc_debug: #00 pc 000000000001470c /apex/com.android.runtime/lib64/libc_malloc_debug.so
  53. 12-19 14:55:02.589 7971 7971 E malloc_debug: #01 pc 0000000000014534 /apex/com.android.runtime/lib64/libc_malloc_debug.so (debug_malloc+108)
  54. 12-19 14:55:02.589 7971 7971 E malloc_debug: #02 pc 00000000000675c0 /system/lib64/libc++.so (operator new(unsigned long)+32)
  55. 12-19 14:55:02.589 7971 7971 E malloc_debug: #03 pc 0000000000001188 /system/bin/androidtest // 通过addr2line 得到未释放内存的指针
  56. 12-19 14:55:02.589 7971 7971 E malloc_debug: #04 pc 000000000007d86c /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+108)
  57. 12-19 14:55:02.589 7971 7971 E malloc_debug: #05 pc 000000000000104c /system/bin/androidtest
  58. 12-19 14:55:02.589 7971 7971 E malloc_debug: #06 pc 00000000000533f4 /apex/com.android.runtime/bin/linker64
  59. 12-19 14:55:02.590 7971 7971 E malloc_debug: Dumping to file: /data/local/tmp/backtrace_heap.7971.exit.txt

案例

稳定性测试一周后,遇到如下问题,android.hardware.graphics.composer@2.1-service 进程占用内存很大。

composer

分析:

  1. 通过 cat /proc/486/smaps 文件,了解到内存占用主要是malloc(anon:libc_malloc)
  2. 由于是服务,不正常退出,所以只有通过发信号的方式去dump trace (kill –s 47 $pid)
  3. 使用native_heapdump_viewer.py 解析两份trace文件,进行比较。确定怀疑点

调试:

1. 由于该进程开机自动启动,需要开机自动设置malloc debug属性值

任意.rc 文件加入如下内容

on post-fs-data

#路径的组权限需要和调试进程保持一致,否则权限错误(即使关闭了selinux),无法dump

mkdir /data/aa  

#当前案例的进程组为system

chown system system /data/aa

#setprop 的长度有限制,尽量使用简单的路径前缀

setprop libc.debug.malloc.options "backtrace=8 leak_track backtrace_dump_on_exit

backtrace_dump_prefix=/data/aa/tra"

2. 抓取dump trace文件

2.1 开机后不进行任何操作,灭屏状态下发送信号47 得到 dump文件

heapdumpfile 为最后需要对比的文件

idle

2.2 开机后复现问题, 然后清除后台所有进程,灭屏待机状态下发送信号47 再次得到 dump文件

idle2

从2.1 和 2.2 可以看出,复现问题之后,同样灭屏清除所有后台的情况下,调试进程的内存大了2M, 并且一直不下降。现在对比两次的heapdumpfile 文件. 找到怀疑点后,通知模块负责人仔细排查代码. 查找问题根因

compare

自动dump脚本(malloc_debug.sh)

  1. if [[ $1 == "--help" || $1 == "help" ]]; then
  2. echo "----------usage-------"
  3. echo "enable dump records_malloc, the malloc debug will use multiple memeory"
  4. echo "---------command: malloc_debug.sh logpath [records_malloc]"
  5. echo "disable dump records_malloc"
  6. echo "---------command: malloc_debug.sh logpath"
  7. exit
  8. elif [[ $1 == "" ]]; then
  9. echo "malloc_debug.sh --help"
  10. exit
  11. fi
  12. logpath=$1
  13. records_malloc_enable=$2
  14. adb root
  15. adb wait-for-device
  16. #need close selinux, others dump failure
  17. adb shell setenforce 0
  18. psstr=`adb shell ps -A | grep "android.hardware.graphics.composer@2.1-service"`
  19. pid=`echo $psstr | awk -F ' ' '{print $2}'`
  20. echo "dump pid = "${pid}
  21. time=$logpath"/"$(date +%m%d%H%M%S)
  22. echo "log path: "$time
  23. mkdir ${time}
  24. #get maps and smaps info
  25. adb shell cat /proc/$pid/maps > $time/$pid"_maps"
  26. adb shell cat /proc/$pid/smaps > $time/$pid"_smaps"
  27. #get all process info before dump
  28. adb shell ps -AT > ./$time/processinfo.txt
  29. #get current meminfo before dump
  30. adb shell dumpsys meminfo | grep composer > ./$time/meminfo
  31. #dump heap trace
  32. adb shell kill -s 47 $pid
  33. if [[ $records_malloc_enable == "records_malloc" ]]; then
  34. #dump records
  35. adb shell kill -s 46 $pid
  36. fi
  37. ###################需要按照路径修改#####
  38. dump_path="/data/aa"
  39. records_malloc_file_name="m"
  40. ###################需要按照路径修改#####
  41. #check dump file
  42. while true
  43. do
  44. file_cnt=`adb shell ls $dump_path | wc -l`
  45. dumpcnt=1
  46. if [[ $records_malloc_enable == "records_malloc" ]]; then
  47. dumpcnt=2
  48. fi
  49. if [[ $file_cnt -eq $dumpcnt ]]; then
  50. echo `adb shell ls $dump_path`
  51. break
  52. fi
  53. sleep 1
  54. done
  55. #find the process name by pid and records pid
  56. #get current meminfo after dump
  57. echo `adb shell dumpsys meminfo | grep composer`
  58. adb pull $dump_path ./$time
  59. dirname="${dump_path##*/}"
  60. mv $time/$dirname/* $time
  61. rm -r ./$time/$dirname
  62. #remove the before dump file
  63. adb shell rm $dump_path/*
  64. #need open selinux, others some app will crash
  65. adb shell setenforce 1
  66. cd $time
  67. #--reverse 内存从大到小排序
  68. native_heapdump_viewer.py *$pid*".txt" --symbols ~/Downloads/symbols --reverse > heapdumpfile

注意事项

遇到dump权限问题,dump路径组 和 进程组不一致导致

dumptrace 文件记录的是触发dump前未释放的内存指针,所以dump文件中不全是有异常的内存指针,需要仔细对比

dumptrace文件中记录的内存指针为内存申请的位置,需要查阅代码确认哪些地方用到了该指针,哪里可能没有释放。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/88860
推荐阅读
  

闽ICP备14008679号