[C++] erreur de seg sur new

Fermé
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 - 15 mai 2009 à 16:29
KX Messages postés 16755 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 12 février 2025 - 19 mai 2009 à 11:40
Bonjour,
Mon problème est assez compliqué, mais en gros, est-il possible qu'un new crée une erreur de segmentation ?
J'ai une classe faite par template dont un bout du constructeur est :
template<class Element> Tableau
{
   Tableau(int d1=1,Element * val=0):_tableau(val)// tableau de type Element*
   {
    if(val==0)
      {
        printf("d1 : %d, val : %d, tab : %d\n",d1,val,_tableau); 
        Element * _tableau0=new Element[d1];
        printf("flag 0\n");
        _tableau=_tableau0;
}
}


La classe est instantier avec double.
On passe un certain nombre de fois dedans sans déclencher d'erreur, puis au bout de 700 fois environ, il se produit une erreur de segmentation sur la ligne Element * _tableau0=new Element[d1];
La sortie console vaut
d1 : 65, val : 0, tab : 0
juste avant de planter.
J'en conclu donc qu'il y a un souci au niveau de new Element[65];, ce qui m'échappe, surtout que l'erreur est reproductible et ceci sur plusieurs machines !
J'ai donc lancé le programme avec Valgrind, et à la fin j'obtiens :
== Process terminating with default action signal 11 (SIGSEGV)
==  Access not within mapped region at address 0x8
==       at 0x8378984: malloc_consolidate (PROG)
etc.

Je ne sais plus quoi faire. Tout idée est la bien venu.
Merci.
config : gcc 3.2.3 sur Red Hat noyau 2.4.21

8 réponses

KX Messages postés 16755 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 12 février 2025 3 020
15 mai 2009 à 17:23
Le destructeur libère-t-il toutes les ressources allouées ?
Ne faudrait-il pas essayer de tester le cas où new échoue ?
Element * _tableau0=new Element[d1];
if (_tableau0!=0) _tableau=_tableau0;
0
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
18 mai 2009 à 08:56
Merci de ta réponse. Je ne vois pas en quoi le destructeur peux influer là dessus.
Par contre, ce que tu proposes ne fonctionnera pas, l'erreur arrive "sur" le new, c'est à dire que je ne peux faire aucune instruction après. "flag 0" ne s'affiche pas.
0
KX Messages postés 16755 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 12 février 2025 3 020
18 mai 2009 à 11:11
Je me disais que si ça une telle erreur se produisait au bout d'un certain nombre d'itérations ça pouvait être parce que le new échoue faute de mémoire disponible auquel cas ça pourrait être le destructeur qui ne désalloue pas toute la mémoire créée auparavant...

Tu l'as peut-être déjà fait mais il y a ici une méthode pour obtenir des informations de débugage supplémentaire sous Linux

Sinon un traitement du signal SIGSEGV permettrait peut-être de contourner le problème si tu penses que celui-ci n'a vraiment aucune raison d'être...
0
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
18 mai 2009 à 11:54
Oui, j'ai déjà passé au debugeur, il m'indique la ligne dite, c'est à dire avec le new.
Le programme ne prend pas de place excessive en mémoire, mais le problème se pose peut être sans saturer la RAM ?
Voici la sortie de GDB :
d1 : 65, val : 0, tab : 0

Program received signal SIGSEGV, Segmentation fault.
0x08378984 in malloc_consolidate ()
(gdb) bt
#0  0x08378984 in malloc_consolidate ()
#1  0x083780cd in _int_malloc ()
#2  0x08377a9e in malloc ()
#3  0x08350fbe in operator new(unsigned) ()
#4  0x0835107f in operator new[](unsigned) ()
#5  0x080e5793 in varti1() () at Tableau.h:41
...
varti1() est la fonction dans laquel se produit l'erreur, Tableau.h le fichier contenant le template.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
KX Messages postés 16755 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 12 février 2025 3 020
18 mai 2009 à 12:53
J'avoue ne pas trop savoir d'où vient l'erreur, et ne pas savoir faire ce que je vais proposer :

L'erreur vient du malloc, peut-être parce qu'il s'agit d'un template et que la taille ne lui est pas connu à l'avance (ce qui paraît absurde si ça marche un certain nombre de fois avant de planter)

Mais si tu sais faire (moi pas) je pense qu'il faudrait essayer de réaliser le new[] manuellement, c'est à dire faire toi même ton alloc et ton malloc spécifiquement pour cette classe, et y inclure un affichage pour voir quand ça plantera (parce que ça devrait planter) et ainsi obtenir plus d'information sur l'erreur...
0
As-tu essayé quelque chose du genre:
Element * _tableau0=new Element[d1];
printf ("%p\n", _tableau0);

simplement pour voir comment évolue la valeur du pointeur et voir s'il y a plantage toujours pour la même valeur.
D'autre part, est-il possible le raccourcir le code au maximum (mais qu'il plante toujours), afin que nous puissions voir ce qui se passe chez nous ?
0
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
19 mai 2009 à 08:16
Salut.
merci KX, mais je me sent dépasser par ce que tu proposes.
Loupius.
Bien entendu, j'ai tenté ce que tu dit, mais comme je plante SUR le new, il n'y a pas d'autre instruction exécuter après, donc c'est un peu l'impasse.
En ce qui concerne le code, il s'agît d'un programme scientifique, d'environ 1500 fichiers (que je n'ai pas écris moi même). L'erreur se produit pour un exécutable bien précis, avec un jeu de données (une configuration d'exécution) bien précis. Au point que le gars de la maintenance n'arrive pas à la reproduire.
Ce que je trouve très bizarre, c'est que ce bout de code est effectué plusieurs dizaines de fois avant de produire une erreur.
Serait il possible que le debug se plante d'endroit d'erreur dans le source (improbable vu les printf que je fais) ou qu'il faille un certain temps pour que le SIGSEG soit "capter", c'est à dire que l'erreur découlerai de ce qui a été fait avant ?
0
KX Messages postés 16755 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 12 février 2025 3 020
19 mai 2009 à 11:40
Serait il possible (...) qu'il faille un certain temps pour que le SIGSEG soit "capter"
Non en aucun cas, les signaux sont asynchrones, donc immédiatement détectés...

Pour le reste, des infos sur malloc, il semble que l'on pourrait s'en servir comme ça :
Element * _tableau0=malloc(d1*sizeof(Element));
if (_tableau0==NULL) printf("malloc==NULL"\n); // pas d'allocation mémoire
else _tableau=_tableau0;
En espérant que si erreur il y a, Loupius ou un autre puisse me corriger...
0