2010-06-07 34 views
54

Je suis en train de mettre en œuvre un algorithme polynomial diviser pour régner afin de pouvoir le comparer à une implémentation OpenCL, mais je ne peux pas obtenir malloc pour fonctionner. Quand je lance le programme, il alloue un tas de choses, vérifie certaines choses, puis envoie le size/2 à l'algorithme. Puis, quand je frappe la ligne malloc encore, il recrache ceci:Pourquoi j'obtiens une erreur d'assertion C malloc?

malloc.c: 3096: SysMalloc: Assertion `(old_top == (((mbinptr) (((char *) & ((av) - > bins [((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) & & old_size == 0) || ((unsigned long) (old_size)> = (unsigned long) ((((builtin_offsetof (struct malloc_chunk, fd_nextsize)) + ((2 * (sizeof (taille_t))) - 1)) & ~ ((2 * (sizeof (size_t))) - 1))) & & ((old_top) -> taille & 0x1) & & ((unsigned long) old_end & pagemask) == 0) » a échoué. Aborted

La ligne en question est la suivante:

int *mult(int size, int *a, int *b) { 
    int *out,i, j, *tmp1, *tmp2, *tmp3, *tmpa1, *tmpa2, *tmpb1, *tmpb2,d, *res1, *res2; 
    fprintf(stdout, "size: %d\n", size); 

    out = (int *)malloc(sizeof(int) * size * 2); 
} 

je vérifier la taille d'un fprintf, et il est un nombre entier positif (habituellement 50 à ce moment). J'ai essayé d'appeler malloc avec un nombre simple ainsi et je reçois toujours l'erreur. Je suis juste perplexe à ce qui se passe, et rien de Google que j'ai trouvé jusqu'ici n'est utile.

Des idées? Que se passe-t-il? J'essaie de comprendre comment compiler un nouveau GCC au cas où il s'agirait d'une erreur de compilation, mais j'en doute vraiment.

+0

Je soupçonne que le problème est en fait une ligne avant celle-là. Peut-être un double gratuit? –

+0

troisième ligne du programme: int * mult (taille de int, int * a, int * b) { \t int * out, i, j, * tmp1, * tmp2, * TMP3, * tmpa1 , * tmpa2, * tmpb1, * tmpb2, d, * res1, * res2; Fprintf (stdout, "taille:% d \ n", taille) \t \t \t out = (int *) malloc (sizeof (int) * taille * 2); – Chris

Répondre

65

99,9% de chances que vous avez la mémoire corrompue (sur- ou sous-coulé un tampon, écrit à un pointeur après qu'il a été libéré, appelé gratuitement deux fois sur le même pointeur, etc.)

exécuter votre code sous Valgrind pour voir où votre programme a fait quelque chose d'incorrect.

+1

corrigé. Valgrind a vraiment aidé. J'ai transcrit mon ancien code matlab et j'ai eu une boucle for qui a traversé j, puis à l'intérieur j'ai fait j ++ qui a le plus écrasé le tableau sur lequel il était en train d'écrire et qui a causé l'échec de malloc. merci pour l'aide! – Chris

+0

Valgrind était juste l'outil dont j'avais besoin pour comprendre ce qui se passait quand j'ai eu cette erreur. Merci de le mentionner. – alexwells

+1

J'ai fait la construction propre et cela a fonctionné correctement. –

1

Nous avons obtenu cette erreur, car nous avons oublié de multiplier par sizeof (int). Notez l'argument de malloc (..) est un nombre d'octets, pas le nombre de mots machine ou autre.

0

je PORTAGE une application de Visual C gcc sur Linux et j'ai eu le même problème avec

malloc.c: 3096: SysMalloc: Assertion gcc sur UBUNTU 11.

J'ai déplacé le même code vers une distribution Suse (sur un autre ordinateur) et je n'ai aucun problème.

Je suppose que les problèmes ne sont pas dans nos programmes, mais dans la propre libc.

40

Pour vous donner une meilleure compréhension de pourquoi cela se produit, je voudrais développer la réponse @ r-samuel-klatchko un peu. Quand vous appelez malloc, ce qui se passe réellement est un peu plus compliqué que de vous donner juste un morceau de mémoire pour jouer avec. Sous le capot, malloc garde également quelques informations d'entretien sur la mémoire qu'il vous a donné (le plus important, sa taille), de sorte que lorsque vous appelez free, il sait des choses comme la quantité de mémoire à libérer. Cette information est généralement conservée juste avant l'emplacement de mémoire qui vous est retourné par malloc. Des informations plus exhaustives sont disponibles on the internet™, mais le (très) idée de base est quelque chose comme ceci:

+------+-------------------------------------------------+ 
+ size |     malloc'd memory    + 
+------+-------------------------------------------------+ 
     ^-- location in pointer returned by malloc 

Sur cette base (et simplifie grandement les choses), lorsque vous appelez malloc, il a besoin d'obtenir un pointeur vers la prochaine partie de la mémoire disponible. Une façon très simple de faire cela est de regarder le peu de mémoire précédente qu'il a donné, et de déplacer size octets plus bas (ou plus) en mémoire. Avec cette mise en œuvre, vous vous retrouvez avec votre mémoire à la recherche quelque chose comme ça après l'attribution p1, p2 et p3:

+------+----------------+------+--------------------+------+----------+ 
+ size |    | size |     | size |   + 
+------+----------------+------+--------------------+------+----------+ 
     ^- p1     ^- p2      ^- p3 

ce donc, est la cause de votre erreur? Eh bien, imaginez que votre code écrase erronément la quantité de mémoire que vous avez allouée (soit parce que vous avez alloué moins que nécessaire car c'était votre problème ou parce que vous utilisez les mauvaises conditions aux limites quelque part dans votre code). Supposons que votre code écrive autant de données à p2 qu'il commence à écraser ce qui est dans le champ de p3. Lorsque vous appelez maintenant malloc, il regarde le dernier emplacement de mémoire qu'il a retourné, regarde son champ de taille, passe à p3 + size puis commence à allouer de la mémoire à partir de là. Toutefois, comme votre code a été remplacé par size, cet emplacement de mémoire ne se trouve plus après la mémoire allouée précédemment.

Inutile de dire que cela peut faire des ravages! Les implémenteurs de malloc ont donc mis en place un certain nombre d '"assertions", ou vérifications, qui essayent de faire un tas de vérifications de santé mentale pour attraper ceci (et d'autres problèmes) si elles sont sur le point de se produire. Dans votre cas particulier, ces affirmations sont violées, et donc malloc, vous disant que votre code était sur le point de faire quelque chose qu'il ne devrait pas faire. Comme précédemment indiqué, ceci est une simplification grossière, mais elle est suffisante pour illustrer le point. La mise en œuvre de la glibc de malloc est de plus de 5k lignes, et il y a eu beaucoup de recherches sur la façon de construire de bons mécanismes d'allocation de mémoire dynamique, donc couvrir tout dans une réponse SO n'est pas possible. J'espère que cela vous a donné une idée de ce qui cause réellement le problème!

+0

Ceci devrait être la réponse acceptée .. –

1

Je reçu le message suivant, semblable à votre celui-ci:

 

    program: malloc.c:2372: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1)) & ~((2 *(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long) old_end & pagemask) == 0)' failed. 

fait une erreur que certains appellent la méthode avant, lors de l'utilisation malloc. Écrasé de manière erronée le signe de multiplication '*' avec un '+' lors de la mise à jour du facteur après l'opérateur sizeof() lors de l'ajout d'un champ au tableau char non signé.

Voici le code responsable de l'erreur dans mon cas:

 

    UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)+5); 
    b[INTBITS]=(some calculation); 
    b[BUFSPC]=(some calculation); 
    b[BUFOVR]=(some calculation); 
    b[BUFMEM]=(some calculation); 
    b[MATCHBITS]=(some calculation); 

Dans une autre méthode plus tard, je malloc à nouveau et il produit le message d'erreur ci-dessus. L'appel était (assez simple):

 

    UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)*50); 

Pensez en utilisant le « + » - signe le 1er appel, ce qui conduit à une mauvaise calcul en combinaison avec l'initialisation immédiate du tableau après (écrasement mémoire qui n'a pas été alloué au tableau), a apporté une certaine confusion à la carte mémoire de malloc. Par conséquent, le 2ème appel a mal tourné.

0

J'ai eu le même problème, j'ai utilisé malloc sur n à nouveau dans une boucle pour l'ajout de nouvelles données char * chaîne. J'ai fait face au même problème, mais après avoir libéré la mémoire allouée void free() problème ont été triés