linux下程序运行到malloc处数次后出错,请教可能的出错原因,谢谢

时间:2022-10-01 19:26:04
简单说来就是在做小规模测试的时候仿佛没有问题,但是在大数据集测试时,这个动态分配并且有free操作的结构在malloc处运行了多次,系统给出如下出错信息:
Program received signal SIGSEGV, Segmentation fault.
(gdb) where
#0  0x400b0279 in free () from /lib/tls/libc.so.6
#1  0x400b1dfc in malloc () from /lib/tls/libc.so.6
#2  0x080729f0 in insert_write_entry (p=0xbffbf940, call_list=0x80a8e18, address=268440796, func=2, func_call_time=296999,
    now=300325) at profiling.c:439     ------------//该行为下面的malloc语句行
#3  0x0804b694 in sim_main () at mem_profiling.c:129
#4  0x0805b74c in main (argc=4, argv=0xbffffa24, envp=0xbffffa38) at main.c:512

代码如下:
struct p_write_entry_t * cur, * temp;
temp = (struct p_write_entry_t *)malloc(sizeof(struct p_write_entry_t));

说明一下:不存在内存不够的问题;因为以前已经跑通了,现在在优化,内存空间要求上应该不存在问题。

不知道有哪些方面的原因可以这样?请赐教,谢谢:)

15 个解决方案

#1


没遇到过,个人认为不会是系统的原因

帮你顶=待高人解答吧。

#2


#0 0x400b0279 in free () from /lib/tls/libc.so.6
#1 0x400b1dfc in malloc () from /lib/tls/libc.so.6

what the hell...
从没经历过。帮顶。。

建议用 valgrind 的 memcheck 辅助检查一下看看有没有更多隐含的错误,也许可以帮助推断。

#3


很显然,问题是因为内存越界造成的,这样的事情我遇到过很多次。
比如你分配了一块内存,但是在操作过程中出现了溢出(上溢或是下溢,从你的情况看,应该是下溢,也就是说你操作了内存指针偏移为负数的空间);导致这块内存在回收时因为其隐含在下溢空间内信息被异常修改,从而被加入到错误的内存空闲块队列中,当这块内存再次分配就会出现问题。

建议对你代码操作内存的地方做下溢检查,应该可以发现问题的。

HelianSiS
2006/10/17

#4


似乎楼上狠有道理

#5


谢谢 HelianSiS,那请问典型的内存下溢操作是什么呢?空栈时出栈,或者其他什么?
我改动的地方基本都是属于双链的增删操作,怎么会产生下溢不大明白。谢谢:)

#6


象下面这样的代码就是一个下溢的例子。
问题也许不在于你所改动的地方,也可能是以前代码的残留问题。
这样的问题引发错误本质上和内存的使用程度有比较大的关系,内存紧张这样的问题暴露
出来的概率也非常高。用动态内存扫描工具找一找吧。

long index = -1;
char * ptr = malloc(100);
if (ptr)
{
    ptr[index] = '\0';//内存下溢!!!
    free(ptr);
}

HelianSiS
2006/10/17

#7


我对linux还不是太熟悉,刚搜了下动态内存扫描工具没有发现linux下使用的;能说得详细一些么?如使用什么工具,简单的操作等,真的谢谢啊~

#8


Helianthus:

仔细看 gdb 的 where 输出了么?free 从 malloc 中被调用,怎么解释?

检查程序的内存使用问题就用我说的 valgrind

#9


好的,谢谢Wolf0403

#10


Wolf0403网友,你好:
   你问的问题很不错。
   我们看到的函数调用栈显示正如你所说的,malloc中嵌套调用了free。
   但是这之间并没有关系。malloc函数的内部实现有很多,为什么就不能
   有内部间接调用free的?事实上我在一些自成体系的嵌入式软件中的memory
   模块里面就发现类似的例子。
   我还是把我当时分析这个问题的思路大致说一说,
   1. 首先从问题的描述和现场的堆栈函数调用关系,说明程序CRASH在free函数中。
      在通常情况下,除非接口传入的参数有误,一般情况下象free这一类的函数
      是不会出问题(当然,memory模块的核心数据被破坏也会导致类似的问题)
   2. 可是因为malloc函数的参数接口非常简单,只有一个数据块的长度,因此我们
      可以立即知道这次CRASH不是因为非法参数导致的,问题出在了MEMORY自己的核心
      数据上。
   3. 正如我刚才和你说的,我曾经遇到过这样的版本,malloc分配内存是根据输入参数
      需要内存块的大小来决定从内部空闲内存块队列上某一个具体大小队列中获取指定的
      数据。现在CRASH了,说明这里面的数据出现了问题。
   4. 在通常情况下,我们是不能对MEMORY数据的内存破坏的。当时如果我们对分配的
      内存块操作溢出的话,事情就可能发生变化。因为大多数MEMORY模块都会在分配给
      用户内存块前端预留一定的字节空间用于说明该分配内存的信息,如大小信息等。
      这样当内存被回收的时候,MEMORY模块就能根据前端的信息快速的定位出该内存块
      应该被回收到哪一个SIZE的内存队列中。当时如果这个SIZE信息被CRASH的话,
      由于被添加到错误的队列上,后续再执行内存分配就会出现问题,这也是我为什么说
      可以先检查下溢的原因吧。
   5. 至于你说的为什么malloc会调用free,老实说我也不知道。当时我觉得这取决于malloc
      的内部实现,而我曾经看过这样的实现,所以我不觉得奇怪。
   6. 当然,从我上面的个人的分析来看,也许不是内存下溢造成的,只是我个人觉得这种
      方式的可能性大一些。至于LINUX下面对内存分析的工具,MEM_WATCH,valgrind都可以。
      更简单的是利用MEM_WATCH的思路自己对malloc、free等函数直接重定向更简单一些吧。

   当然,这只是我个人对这个问题的初步分析。如果有现场的话,可以直接看看寄存器就知道
CRASH的指令到底试图操作的是哪一个内存队列,不过这需要作者直接再深入看看。


谢谢!

HelianSiS
2006/10/17
   7.

#11


可能下标越界.溢出了..
回答完毕

#12


同意:Helianthus()

#13


呵呵,我只是觉得这里有点奇怪。

出错最常见的原因是某处越界访问写入数据,但是在进行静态代码分析和使用 valgrind 跟踪之前我不想做无谓的猜测。

#14


怎么说呢,我个人觉得事情的确有很多可能性,但是我们的作用就是利用手里得到的信息以
减少问题的分支数目。所以不能说根据部分事实做出的有依据的判断是无谓的猜测,事实上从前面我个人的分析也可以看出,我个人觉得在这个例子中,下溢造成问题的可能性远比上溢大得多。问题出在库函数内部,在参数不可能引入问题的情况下,自然是MEMORY内部的核心数据出了
问题。如果说没有工具,我们对问题就无能为力了?
    当然,我也支持对代码的分析,但是代码很多,如果没有方向,在程序规模很大的时候我们往往会迷失方向的。依据问题的现场信息,尽可能地提供一个查找问题的方向怎么能说是无谓的猜测呢?我不是很理解。
    当然,每一个人都有自己的做事风格,我理解。我无疑引发人生攻击,希望各位不要误解,谢谢!

HelianSis
2006/10/18

#15


呵呵,应该我出来道歉哈,因为是我引起的
不过这个事情可以看出无论是HelianSis还是Wolf0403都是很严谨认真的人,大家在技术和学术上的讨论发生争论都是很正常的,大家的目的只有一个,在讨论中提高,如果得到了,那么大家都收获了,而且不打不相识嘛。
根据大家的建议,我把这个bug改掉了,原因呢,是我们用的pisa指令集的交叉编译器版本有点低,我对一个有自身带5个指针链的核心数据结构操作产生了其中一个指针的野指针操作,在一个比较小概率的地方发生了double-free而没有检测出来。
自己能抛砖引玉非常荣幸,不过程序又遇到其他bug了,应该还是差不多的原因,接着调...
再次谢谢大家!

#1


没遇到过,个人认为不会是系统的原因

帮你顶=待高人解答吧。

#2


#0 0x400b0279 in free () from /lib/tls/libc.so.6
#1 0x400b1dfc in malloc () from /lib/tls/libc.so.6

what the hell...
从没经历过。帮顶。。

建议用 valgrind 的 memcheck 辅助检查一下看看有没有更多隐含的错误,也许可以帮助推断。

#3


很显然,问题是因为内存越界造成的,这样的事情我遇到过很多次。
比如你分配了一块内存,但是在操作过程中出现了溢出(上溢或是下溢,从你的情况看,应该是下溢,也就是说你操作了内存指针偏移为负数的空间);导致这块内存在回收时因为其隐含在下溢空间内信息被异常修改,从而被加入到错误的内存空闲块队列中,当这块内存再次分配就会出现问题。

建议对你代码操作内存的地方做下溢检查,应该可以发现问题的。

HelianSiS
2006/10/17

#4


似乎楼上狠有道理

#5


谢谢 HelianSiS,那请问典型的内存下溢操作是什么呢?空栈时出栈,或者其他什么?
我改动的地方基本都是属于双链的增删操作,怎么会产生下溢不大明白。谢谢:)

#6


象下面这样的代码就是一个下溢的例子。
问题也许不在于你所改动的地方,也可能是以前代码的残留问题。
这样的问题引发错误本质上和内存的使用程度有比较大的关系,内存紧张这样的问题暴露
出来的概率也非常高。用动态内存扫描工具找一找吧。

long index = -1;
char * ptr = malloc(100);
if (ptr)
{
    ptr[index] = '\0';//内存下溢!!!
    free(ptr);
}

HelianSiS
2006/10/17

#7


我对linux还不是太熟悉,刚搜了下动态内存扫描工具没有发现linux下使用的;能说得详细一些么?如使用什么工具,简单的操作等,真的谢谢啊~

#8


Helianthus:

仔细看 gdb 的 where 输出了么?free 从 malloc 中被调用,怎么解释?

检查程序的内存使用问题就用我说的 valgrind

#9


好的,谢谢Wolf0403

#10


Wolf0403网友,你好:
   你问的问题很不错。
   我们看到的函数调用栈显示正如你所说的,malloc中嵌套调用了free。
   但是这之间并没有关系。malloc函数的内部实现有很多,为什么就不能
   有内部间接调用free的?事实上我在一些自成体系的嵌入式软件中的memory
   模块里面就发现类似的例子。
   我还是把我当时分析这个问题的思路大致说一说,
   1. 首先从问题的描述和现场的堆栈函数调用关系,说明程序CRASH在free函数中。
      在通常情况下,除非接口传入的参数有误,一般情况下象free这一类的函数
      是不会出问题(当然,memory模块的核心数据被破坏也会导致类似的问题)
   2. 可是因为malloc函数的参数接口非常简单,只有一个数据块的长度,因此我们
      可以立即知道这次CRASH不是因为非法参数导致的,问题出在了MEMORY自己的核心
      数据上。
   3. 正如我刚才和你说的,我曾经遇到过这样的版本,malloc分配内存是根据输入参数
      需要内存块的大小来决定从内部空闲内存块队列上某一个具体大小队列中获取指定的
      数据。现在CRASH了,说明这里面的数据出现了问题。
   4. 在通常情况下,我们是不能对MEMORY数据的内存破坏的。当时如果我们对分配的
      内存块操作溢出的话,事情就可能发生变化。因为大多数MEMORY模块都会在分配给
      用户内存块前端预留一定的字节空间用于说明该分配内存的信息,如大小信息等。
      这样当内存被回收的时候,MEMORY模块就能根据前端的信息快速的定位出该内存块
      应该被回收到哪一个SIZE的内存队列中。当时如果这个SIZE信息被CRASH的话,
      由于被添加到错误的队列上,后续再执行内存分配就会出现问题,这也是我为什么说
      可以先检查下溢的原因吧。
   5. 至于你说的为什么malloc会调用free,老实说我也不知道。当时我觉得这取决于malloc
      的内部实现,而我曾经看过这样的实现,所以我不觉得奇怪。
   6. 当然,从我上面的个人的分析来看,也许不是内存下溢造成的,只是我个人觉得这种
      方式的可能性大一些。至于LINUX下面对内存分析的工具,MEM_WATCH,valgrind都可以。
      更简单的是利用MEM_WATCH的思路自己对malloc、free等函数直接重定向更简单一些吧。

   当然,这只是我个人对这个问题的初步分析。如果有现场的话,可以直接看看寄存器就知道
CRASH的指令到底试图操作的是哪一个内存队列,不过这需要作者直接再深入看看。


谢谢!

HelianSiS
2006/10/17
   7.

#11


可能下标越界.溢出了..
回答完毕

#12


同意:Helianthus()

#13


呵呵,我只是觉得这里有点奇怪。

出错最常见的原因是某处越界访问写入数据,但是在进行静态代码分析和使用 valgrind 跟踪之前我不想做无谓的猜测。

#14


怎么说呢,我个人觉得事情的确有很多可能性,但是我们的作用就是利用手里得到的信息以
减少问题的分支数目。所以不能说根据部分事实做出的有依据的判断是无谓的猜测,事实上从前面我个人的分析也可以看出,我个人觉得在这个例子中,下溢造成问题的可能性远比上溢大得多。问题出在库函数内部,在参数不可能引入问题的情况下,自然是MEMORY内部的核心数据出了
问题。如果说没有工具,我们对问题就无能为力了?
    当然,我也支持对代码的分析,但是代码很多,如果没有方向,在程序规模很大的时候我们往往会迷失方向的。依据问题的现场信息,尽可能地提供一个查找问题的方向怎么能说是无谓的猜测呢?我不是很理解。
    当然,每一个人都有自己的做事风格,我理解。我无疑引发人生攻击,希望各位不要误解,谢谢!

HelianSis
2006/10/18

#15


呵呵,应该我出来道歉哈,因为是我引起的
不过这个事情可以看出无论是HelianSis还是Wolf0403都是很严谨认真的人,大家在技术和学术上的讨论发生争论都是很正常的,大家的目的只有一个,在讨论中提高,如果得到了,那么大家都收获了,而且不打不相识嘛。
根据大家的建议,我把这个bug改掉了,原因呢,是我们用的pisa指令集的交叉编译器版本有点低,我对一个有自身带5个指针链的核心数据结构操作产生了其中一个指针的野指针操作,在一个比较小概率的地方发生了double-free而没有检测出来。
自己能抛砖引玉非常荣幸,不过程序又遇到其他bug了,应该还是差不多的原因,接着调...
再次谢谢大家!