1

I am writing code to use a library called SCIP (solves optimisation problems). The library itself can be compiled in two ways: create a set of .a files, then the binary, OR create a set of shared objects. In both cases, SCIP is compiled with it's own, rather large, Makefile.

I have two implementations, one which compiles with the .a files (I'll call this program 1), the other links with the shared objects (I'll call this program 2). Program 1 is compiled using a SCIP-provided makefile, whereas program 2 is compiled using my own, much simpler makefile.

The behaviour I'm encountering occurs in the SCIP code, not in code that I wrote. The code extract is as follows:

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)))  
   .  
   .  
   .  
}  

If I debug this code in gdb, and step through BMSallocMemory_call() in order to see what's happening, and view the contents of *((SCIP*)(ptr)), I get the following output:

Program 1 gdb output:

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}  

Program 2 gdb output:

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}  

The only reason I can think of is that in either program 1's or SCIP's makefile, there is some sort of option that forces malloc to initialise memory it allocates. I simply must learn why the structure is initialised in the compiled implementation, and is not in the shared object implementation.

unwind
  • 391,730
  • 64
  • 469
  • 606
Andy
  • 11
  • 1

3 Answers3

2

I doubt the difference has to do with how the two programs are built.

malloc does not initialize the memory it allocates. It may so happen by chance that the memory you get back is filled with zeroes. For example, a program that's just started is more likely to get zero-filled memory from malloc than a program that's been running for a while and allocating/deallocating memory.

edit You may find the following past questions of interest:

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • I've played a bit more with the code, and swapped malloc out for calloc. After re-compiling everything, I get the same behaviour, ie, program 2's SCIP structure is still not initialised. I am even more confused. Just to clarify, program 2 is actually python code, calling an SO created by SWIG (a python-C interface generator). I recently wrote some standard C code to access the SCIP shared objects, removing Python and SWIG from the picture, and when the ptr is allocated, it is again a 'zeroed-out' block of memory, regardless of whether malloc or calloc is used. – Andy Dec 13 '10 at 11:23
  • @Andy With regards to your first point, this is indeed quite odd. What's the exact `calloc` call you're using, immediately after which the structure is non-zero? – NPE Dec 13 '10 at 11:23
  • @Andy It does look correct. Can you print out the value of `size` immediately before the `calloc` (i.e. after the `MAX`). – NPE Dec 13 '10 at 11:29
  • 84, although not ignore what I said about calloc, as calloc appears to be working correctly for program 2. – Andy Dec 13 '10 at 11:39
  • @Andy What exactly is happening that requires further explanation? We know that `malloc` doesn't initialize memory as a rule, but sometimes might return a block of zeroes. Is this inconsistent with what you're seeing? – NPE Dec 13 '10 at 11:43
  • For program 1, and the C shared-object implementation, malloc consistently returns pointers to zeroed-out memory, but for program 2 (the SWIG/Python shared-object implementation), malloc does not return zeroed-out memory. I was hoping to find a way to have malloc return zeroed-out memory for program 2 without changing the SCIP source, ie, have the same behaviour as the other programs. – Andy Dec 13 '10 at 11:46
  • While there are ways to wrap/replace malloc with your own (http://stackoverflow.com/questions/262439/create-a-wrapper-function-for-malloc-and-free-in-c), I would first make sure that your explanation re program#1 is correct. While by not means impossible, I find it rather odd. – NPE Dec 13 '10 at 11:51
  • Regarding what the output of program 1 is, or how it works? I can supply the code and makefile. Code: http://codeviewer.org/view/code:150f Makefile: http://codeviewer.org/view/code:1510 – Andy Dec 13 '10 at 13:02
1

Initialization of malloc-ed memory may be implementation dependent. Implementations are free not to do so for performance reasons, but they could initialize the memory for example in debug mode.

One more note. Even uninitialized memory may contain zeros.

Juraj Blaho
  • 13,301
  • 7
  • 50
  • 96
0

On Linux, according to this thread, memory will be zero-filled when first handed to the application. Thus, if your call to malloc() caused the program's heap to grow, the "new" memory will be zero-filled.

One way to verify is of course to just step into malloc() from your routine, that should make it pretty clear whether or not it contains code to initialize the memory, directly.

unwind
  • 391,730
  • 64
  • 469
  • 606