2010-12-13 3 views
1

J'écris du code pour utiliser une bibliothèque appelée SCIP (résout des problèmes d'optimisation). La bibliothèque elle-même peut être compilée de deux façons: créer un ensemble de fichiers .a, puis le binaire, OU créer un ensemble d'objets partagés. Dans les deux cas, SCIP est compilé avec son propre Makefile.Qu'est-ce qui pourrait causer l'initialisation de la mémoire par malloc?

J'ai deux implémentations, une qui compile avec les fichiers .a (j'appellerai ce programme 1), les autres liens avec les objets partagés (j'appellerai ce programme 2). Le programme 1 est compilé en utilisant un makefile fourni par SCIP, alors que le programme 2 est compilé en utilisant mon propre makefile, beaucoup plus simple.

Le comportement que je rencontre se produit dans le code SCIP, pas dans le code que j'ai écrit. L'extrait de code est le suivant:

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

Si je déboguer ce code dans gdb, et l'étape par BMSallocMemory_call() afin de voir ce qui se passe, et afficher le contenu de *((SCIP*)(ptr)), je reçois la sortie suivante:

programme 1 sortie 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} 

programme 2 sortie 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} 

La seule raison à laquelle je peux penser est que dans le makefile du programme 1 ou de SCIP, il y a une sorte d'option qui oblige malloc à initialiser la mémoire qu'il alloue. Je dois simplement apprendre pourquoi la structure est initialisée dans l'implémentation compilée et n'est pas dans l'implémentation de l'objet partagé.

+0

De quel système d'exploitation est-ce le cas? – sharptooth

Répondre

1

L'initialisation de la mémoire malloc-éd peut dépendre de l'implémentation. Les implémentations sont libres de ne pas le faire pour des raisons de performances, mais elles peuvent initialiser la mémoire par exemple en mode débogage.

Une note de plus. Même la mémoire non initialisée peut contenir des zéros.

2

Je doute que la différence a à voir avec la façon dont les deux programmes sont construits.

malloc n'initialise pas la mémoire allouée. Cela peut arriver par hasard que la mémoire que vous récupérez soit remplie de zéros. Par exemple, un programme qui vient de démarrer est plus susceptible d'obtenir une mémoire remplie de zéros à partir de malloc qu'un programme exécuté depuis un certain temps et d'allouer/libérer de la mémoire.

modifier Vous pouvez trouver les questions d'intérêt passées suivantes:

+0

J'ai joué un peu plus avec le code, et j'ai échangé malloc pour calloc. Après avoir recompilé tout, j'ai le même comportement, c'est-à-dire que la structure SCIP du programme 2 n'est toujours pas initialisée. Je suis encore plus confus. Juste pour clarifier, le programme 2 est en fait du code python, appelant un SO créé par SWIG (un générateur d'interface python-C). J'ai récemment écrit du code C standard pour accéder aux objets partagés SCIP, en supprimant Python et SWIG de l'image, et quand le ptr est alloué, il s'agit à nouveau d'un bloc de mémoire 'zeroed-out', que malloc ou calloc soit utilisé . – Andy

+0

@Andy En ce qui concerne votre premier point, c'est en effet assez étrange. Quel est l'appel 'calloc' exact que vous utilisez, immédiatement après lequel la structure est différente de zéro? – NPE

+0

C'était "ptr = calloc (1, taille);", je suppose que c'est correct? – Andy

0

Sur Linux, selon this thread, la mémoire sera nulle rempli lors de la première remise à l'application. Ainsi, si votre appel à malloc() a provoqué une augmentation du tas du programme, la "nouvelle" mémoire sera remplacée par zéro.

Une façon de vérifier est bien sûr juste l'étape dansmalloc() de votre routine, qui devrait le rendre assez clair si oui ou non il contient du code pour initialiser la mémoire, directement.

Questions connexes