【问题标题】:What could cause malloc to initialise memory?什么可能导致 malloc 初始化内存?
【发布时间】:2010-12-13 10:51:19
【问题描述】:

我正在编写代码以使用名为 SCIP 的库(解决优化问题)。库本身可以通过两种方式编译:创建一组 .a 文件,然后是二进制文件,或者创建一组共享对象。在这两种情况下,SCIP 都是使用它自己的相当大的 Makefile 编译的。

我有两个实现,一个用 .a 文件编译(我称之为程序 1),另一个与共享对象链接(我称之为程序 2)。程序 1 是使用 SCIP 提供的 makefile 编译的,而程序 2 是使用我自己的更简单的 makefile 编译的。

我遇到的行为发生在 SCIP 代码中,而不是我编写的代码中。代码摘录如下:

void* BMSallocMemory_call(size_t size)  
{  
   void* ptr;  

   size = MAX(size, 1);  
   ptr = malloc(size);  

   // This is where I call gdb print statements.  

   if( ptr == NULL )  
   {  
      printf("ERROR - unable to allocate memory for a SCIP*.\n");  
   }  
   return ptr;  
}

void SCIPcreate(SCIP** A)  
{  
   *A = (SCIP*)BMSallocMemory_call(sizeof(**(A)))  
   .  
   .  
   .  
}  

如果我在 gdb 中调试此代码,并单步执行 BMSallocMemory_call() 以查看发生了什么,并查看 *((SCIP*)(ptr)) 的内容,我会得到以下输出:

程序 1 gdb 输出:

289    size = MAX(size, 1);  
(gdb) step  
284 {  
(gdb)   
289    size = MAX(size, 1);  
(gdb)   
290    ptr = malloc(size);  
(gdb) print ptr  
$1 = <value optimised out>  
(gdb) step  
292    if( ptr == NULL )  
(gdb) print ptr  
$2 = <value optimised out>  
(gdb) step  
290    ptr = malloc(size);  
(gdb) print ptr  
$3 = (void *) 0x8338448  
(gdb) print *((SCIP*)(ptr))  
$4 = {mem = 0x0, set = 0x0, interrupt = 0x0, dialoghdlr = 0x0, totaltime = 0x0, stat = 0x0, origprob = 0x0, eventfilter = 0x0, eventqueue = 0x0, branchcand = 0x0, lp = 0x0, nlp = 0x0, relaxation = 0x0, primal = 0x0, tree = 0x0, conflict = 0x0, cliquetable = 0x0, transprob = 0x0, pricestore = 0x0, sepastore = 0x0, cutpool = 0x0}  

程序 2 gdb 输出:

289    size = MAX(size, 1);  
(gdb) step  
290    ptr = malloc(size);  
(gdb) print ptr  
$1 = (void *) 0xb7fe450c  
(gdb) print *((SCIP*)(ptr))  
$2 = {mem = 0x1, set = 0x8232360, interrupt = 0x1, dialoghdlr = 0xb7faa6f8, totaltime = 0x0, stat = 0xb7fe45a0, origprob = 0xb7fe4480, eventfilter = 0xfffffffd, eventqueue = 0x1, branchcand = 0x826e6a0, lp = 0x8229c20, nlp = 0xb7fdde80, relaxation = 0x822a0d0, primal = 0xb7f77d20, tree = 0xb7fd0f20, conflict = 0xfffffffd, cliquetable = 0x1, transprob = 0x8232360, pricestore = 0x1, sepastore = 0x822e0b8, cutpool = 0x0}  

我能想到的唯一原因是,在程序 1 或 SCIP 的 makefile 中,有某种选项强制 malloc 初始化它分配的内存。我只是必须了解为什么结构在编译实现中被初始化,而不是在共享对象实现中。

【问题讨论】:

    标签: c compiler-construction memory-management malloc


    【解决方案1】:

    我怀疑这两个程序的构建方式不同。

    malloc 不会初始化它分配的内存。可能会偶然发生,您返回的内存中充满了零。例如,一个刚刚启动的程序更有可能从malloc 获得零填充的内存,而不是一个已经运行了一段时间并分配/释放内存的程序。

    编辑您可能会发现以下感兴趣的过去问题:

    【讨论】:

    • 我对代码进行了更多尝试,并将 malloc 换成了 calloc。重新编译所有内容后,我得到相同的行为,即程序 2 的 SCIP 结构仍未初始化。我更加困惑。澄清一下,程序 2 实际上是 python 代码,调用由 SWIG(python-C 接口生成器)创建的 SO。我最近写了一些标准的 C 代码来访问 SCIP 共享对象,从图片中删除了 Python 和 SWIG,当分配 ptr 时,它又是一个“归零”的内存块,无论是使用 malloc 还是 calloc .
    • @Andy 关于你的第一点,这确实很奇怪。您正在使用的确切 calloc 调用是什么,紧随其后的结构是非零的?
    • @Andy 看起来确实正确。你能在calloc之前(即MAX之后)打印出size的值吗?
    • 84,虽然不要忽略我所说的关于 calloc 的内容,因为 calloc 似乎在程序 2 中正常工作。
    • @Andy 到底发生了什么需要进一步解释?我们知道malloc 通常不会初始化内存,但有时可能会返回一个零块。这与您所看到的不一致吗?
    【解决方案2】:

    malloc 内存的初始化可能取决于实现。出于性能原因,实现可以不这样做,但它们可以初始化内存,例如在调试模式下。

    还有一个注意事项。即使是未初始化的内存也可能包含零。

    【讨论】:

      【解决方案3】:

      在 Linux 上,根据this thread,当第一次交给应用程序时,内存将被零填充。因此,如果您对malloc() 的调用导致程序堆增长,则“新”内存将被零填充。

      一种验证方法当然是从你的例程中直接进入malloc(),这应该可以很清楚它是否包含直接初始化内存的代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-01
        • 2021-10-16
        • 2022-09-27
        • 1970-01-01
        • 2023-02-10
        • 2019-11-24
        相关资源
        最近更新 更多