写了一个函数:创建一个节点,并将id 全部克隆到新创建的节点,代码如下

static itree_node_t * itree_new2(id_sets_t *  id_sets,unsigned int min,unsigned int max)
{    itree_node_t * new_node = NULL;new_node = calloc(1,sizeof(itree_node_t));assert(new_node);new_node->max = max;new_node->min = min;new_node->id_sets.id_num = id_sets->id_num;new_node->id_sets.id_array_num = ID_PREPARE_MALLOC_SIZE;new_node->id_sets.id_array = calloc(new_node->id_sets.id_array_num,sizeof(unsigned int));assert(new_node->id_sets.id_array);for(int i = 0 ; i < id_sets->id_num;i++){new_node->id_sets.id_array[i] = id_sets->id_array[i];}return new_node;
}

不适用任何特殊编译选项编译这段代码:

gcc   -g -O0  -Wall  $(DEFINES) $(INCLUDE) 

运行后出现下面的结果:

itree init...
realloc(): invalid next size                                                                         ][4%][|]
已放弃 (核心已转储)

使用gdb 看堆栈:

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ffff7de0859 in __GI_abort () at abort.c:79
#2  0x00007ffff7e4b26e in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff7f75298 "%s\n") at ../sysdeps/posix/libc_fatal.c:155
#3  0x00007ffff7e532fc in malloc_printerr (str=str@entry=0x7ffff7f735bb "realloc(): invalid next size") at malloc.c:5347
#4  0x00007ffff7e56fac in _int_realloc (av=av@entry=0x7ffff7faab80 <main_arena>, oldp=oldp@entry=0x424b40, oldsize=oldsize@entry=416, nb=816) at malloc.c:4564
#5  0x00007ffff7e58fb6 in __GI___libc_realloc (oldmem=0x424b50, bytes=800) at malloc.c:3226
#6  0x000000000040235d in itree_node_id_clone (node=0x414510, id_sets=0x4139d8) at ../idps_itree.c:77
#7  0x0000000000401a78 in _itree_insert (tree=0x7fffffffdfa0, pbase=0x42a070, node=0x4139d0) at ../idps_itree.c:281

可以看到出错的位置在itree_node_id_clone 中realloc 失败了。

但是检查代码,这里的代码并没有问题,使用malloc,calloc 替换后情况类似。

于是我们借助clang的sanitizer 来定位问题,使用如下编译选项:

clang -g -O0  -Wall  $(DEFINES) $(INCLUDE) -fsanitize=address -fno-omit-frame-pointer 

后重新编译运行,结果如下:

zison@ubuntu:~/work/idps/car_idps/idps_engine$ ./test/itree_test 5000 100
itree init...
=================================================================                                    ][3%][\]
==55229==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6140002559d0 at pc 0x0000004c7e5a bp 0x7ffde91cf5c0 sp 0x7ffde91cf5b8
WRITE of size 4 at 0x6140002559d0 thread T0#0 0x4c7e59 in itree_new2 /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:53:39#1 0x4c4dbe in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:211:35#2 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#3 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#4 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#5 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#6 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#7 0x4c65e1 in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:350:16#8 0x4c3499 in itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:424:12#9 0x4c8ea5 in main /home/zison/work/idps/car_idps/idps_engine/test/itree_test.c:59:9#10 0x7f7267e1d082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16#11 0x41b31d in _start (/home/zison/work/idps/car_idps/idps_engine/test/itree_test+0x41b31d)0x6140002559d0 is located 0 bytes to the right of 400-byte region [0x614000255840,0x6140002559d0)
allocated by thread T0 here:#0 0x493bd2 in calloc (/home/zison/work/idps/car_idps/idps_engine/test/itree_test+0x493bd2)#1 0x4c7bc2 in itree_new2 /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:48:34#2 0x4c4dbe in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:211:35#3 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#4 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#5 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#6 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#7 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#8 0x4c65e1 in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:350:16#9 0x4c3499 in itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:424:12#10 0x4c8ea5 in main /home/zison/work/idps/car_idps/idps_engine/test/itree_test.c:59:9#11 0x7f7267e1d082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16SUMMARY: AddressSanitizer: heap-buffer-overflow /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:53:39 in itree_new2
Shadow bytes around the buggy address:0x0c2880042ae0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd0x0c2880042af0: fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa0x0c2880042b00: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 000x0c2880042b10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x0c2880042b20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c2880042b30: 00 00 00 00 00 00 00 00 00 00[fa]fa fa fa fa fa0x0c2880042b40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c2880042b50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c2880042b60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c2880042b70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c2880042b80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):

观察结果,发现idps_itree.c:53

这里溢出了,这里才是真正引起问题的地方。检查代码 ,发现在id_sets->id_num 大于ID_PREPARE_MALLOC_SIZE 的情况下,就会出现溢出new_node->id_sets.id_array 的情况。

如果不使用clang 的sanitizer ,程序报错往往是在其他的malloc,calloc,realloc 的地方,出现类似“realloc(): invalid next size”的问题,往往根据报错比较难找到真正出问题的地方。

clang 的sanitizer 不仅能方便的查找内存溢出,还能方便的检查线程死锁等等。有兴趣的可以自行google ,baidu 加深了解。

巧用clang 的sanitize解决realloc,malloc,calloc失败相关推荐

  1. realloc,malloc,calloc的区别

    三个函数的申明分别是:  void* realloc(void* ptr, unsigned newsize);  void* malloc(unsigned size);  void* calloc ...

  2. 内存动态分配之realloc(),malloc(),calloc()与new运算符

    1,malloc与free是C/C++的标准库函数,new/delete是C++的运算符,是C++面向对象的特征,它们都可用于申请动态内存和释放内存. 2,对于非内部数据类型的对象而言,光用maloc ...

  3. C语言学习笔记10-指针(动态内存分配malloc/calloc、realloc、释放free,可变数组实现;Tips:返回指针的函数使用本地变量有风险!;最后:函数指针)

    C语言:指针 1. 指针:保存地址的变量 *p (pointer) ,这种变量的值是内存的地址.   取地址符& 只用于获取变量(有地址的东西)的地址:scanf函数-取地址符   地址的大小 ...

  4. c语言malloc,calloc,realloc函数介绍

    malloc,calloc,realloc动态内存管理函数的出现解决了在某些c语言标准中不能使用变长数组的问题 这三个函数的使用需要头文件stdlib.h,这些函数开辟的空间在堆区,系统不会自动释放, ...

  5. malloc calloc realloc的对比

    函数原型 三个函数的声明分别是: void* realloc(void* ptr, unsigned newsize); void* malloc(unsigned size); void* call ...

  6. Python selenium巧用Javascript脚本注入解决按钮点选问题

    Python selenium巧用Javascript脚本注入解决按钮点选问题 参考文章: (1)Python selenium巧用Javascript脚本注入解决按钮点选问题 (2)https:// ...

  7. 内存分配函数 malloc、realloc、calloc

    C 语言主要提供 malloc.realloc.calloc.alloca 与 aligned_alloc 等内存分配函数来实现对内存的分配功能. 1) malloc 函数原型如下: void * m ...

  8. 内存分布malloc/calloc/realloc/free/new/delete、内存泄露、String模板、浅拷贝与深拷贝以及模拟string类的实现

    内存分布 一.C语言中的动态内存管理方式:malloc/calloc/realloc和free 1.malloc: 从堆上获得指定字节的内存空间,函数声明:void *malloc (int n); ...

  9. C++自学21:动态分配内存(malloc/calloc/realloc/new)/回收内存(free/delete)

    一:malloc函数,请求系统分配内存 // 让系统分配8个字节的内存,这8个字节是连续的,就是一个数组 int* a=(int*)malloc(8); // 如果分配成功,则返回数组首字节的地址,分 ...

最新文章

  1. 【SAP BI】BW如何连接SQLSERVER数据库
  2. virsh 关机_kvm虚拟机不能使用virsh shutdownw命令关闭虚拟机的解决方法
  3. 系统架构设计师考试 重要的部分
  4. vmware创建虚拟机并安装centos7系统
  5. linux硬盘系统安装教程图解,Linux操作系统添加安装新硬盘的方法图解
  6. Selenium WebDriver Api 知识梳理
  7. ArrayList源码解析
  8. 合并时显示是无效的m3u8文件_如何合并m3u8及ts文件
  9. LMS激光传感器的TCP/IP协议问题
  10. thinkphp 提示验证码错误
  11. 复制csdn或者博客园文章时,图片无法直接粘贴过来解决办法
  12. HTML初心自学记录(四)列表超链接
  13. 数据分析入门 | kaggle泰坦尼克任务
  14. python 如何调试uc浏览器_如何使用 UC浏览器开发者版 进行移动端调试
  15. Redis常用命令和操作
  16. vscode如何同时运行多个vue项目
  17. Python之logic
  18. cmd命令 从C盘跳到D盘
  19. python自学第六天之列表增删改查
  20. 谭浩强C语身教程第一章---C措辞概述(2)

热门文章

  1. YOLO v2原理与代码解析
  2. 点云最小二乘法拟合曲线
  3. flash中添加音乐问题
  4. 【紫光同创国产FPGA教程】【第十一章】录音与播放例程
  5. Delphi XE 10 跨平台三层数据库应用教程
  6. RabbitMQ(消息队列)私人学习笔记
  7. [日推荐]『车助手360』车主必备
  8. 【Android 插件化】VirtualApp 接入 ( 在 VirtualApp 工程下创建 Module | 添加依赖 | 启动 VirtualApp 插件引擎 )
  9. 计算机内存数值存储方式进制
  10. JAVA—— HTML