OVH Cloud OVH Cloud

Coredump après un appel de new

21 réponses
Avatar
Gaël Jaffré
Bonjour,

J'ai défini une classe Signature qui utilise plusieurs structures
personnelles (mais aucune autre classe).
Mon problème, c'est que mon programme plante après 2 ou 3 créations
d'objets. Après avoir créé dynamiquement 2 objets, l'allocation me
génère un coredump (sous Linux), avant même l'appel du constructeur.

Signature *s = new Signature();
// ou encore
Signature *s = (Signature*)malloc(sizeof(Signature));

alors que Signature s; fonctionne sans erreur.

Je croyais qu'une allocation mémoire impossible renvoyait NULL, mais
ne générait pas d'erreur.
Quelqu'un comprend t-il comment le programme peut planter à la
création de l'objet ?

Merci


La définition de ma classe est la suivante :

#define SIGN_NB_VAL_MAX 64

class Signature
{
public:
inline Signature(void);
inline Signature(IplImage *im_segmentee);
inline ~Signature(void);
void remplir(IplImage *im_segmentee);
void remplir_completement(IplImage *im_segmentee);
void afficher(void) const;
inline int operator ==(Signature & s2) const;
inline Signature & operator =(const Signature & s);
friend inline double mesure_similarite(const Signature *s1, const
Signature *s2);

private:
couleur couleurs[SIGN_NB_VAL_MAX];
int nb_occ[SIGN_NB_VAL_MAX];
double frequences[SIGN_NB_VAL_MAX];
CvMat *matrice;
int nb_couleurs;
int nb_pixels;
CvMat *mat_signature(void);
};

10 réponses

1 2 3
Avatar
Rémy
"Gaël Jaffré" a écrit dans le message de
news:c8a0dl$r5j$
Bonjour,

J'ai défini une classe Signature qui utilise plusieurs structures
personnelles (mais aucune autre classe).
Mon problème, c'est que mon programme plante après 2 ou 3 créations
d'objets. Après avoir créé dynamiquement 2 objets, l'allocation me
génère un coredump (sous Linux), avant même l'appel du constructeur.

Signature *s = new Signature();
// ou encore
Signature *s = (Signature*)malloc(sizeof(Signature));

alors que Signature s; fonctionne sans erreur.

Je croyais qu'une allocation mémoire impossible renvoyait NULL, mais
ne générait pas d'erreur.
Quelqu'un comprend t-il comment le programme peut planter à la
création de l'objet ?

Merci




Bonjour,

Un malloc/new qui fait un core est généralement symptomatique d'une
structure interne d'allocations de données corrompue.

Probablement que dans le programme, il y a, avant cette allocation, une ou
des écritures en dehors de zones allouées.

Rémy

Avatar
drkm
Gaël Jaffré writes:

Signature *s = new Signature();


[...]

Je croyais qu'une allocation mémoire impossible renvoyait NULL, mais
ne générait pas d'erreur.


#include <new>

Signature * s = new Signature() ;
Signature * s = ( std::nothrow ) new Signature() ;

La première lève une exception `bad_alloc' et la seconde retourne 0,
en cas d'erreur.

--drkm

Avatar
Gaël Jaffré
#include <new>

Signature * s = new Signature() ;
Signature * s = ( std::nothrow ) new Signature() ;

La première lève une exception `bad_alloc' et la seconde retourne 0,
en cas d'erreur.



Merci pour votre réponse.
Mais même en testant les 2 cas, et en rattrapant l'exception, j'ai
toujours un arrêt du programme (et un coredump) sur la ligne
d'allocation mémoire.

Avatar
drkm
Gaël Jaffré writes:

Mais même en testant les 2 cas, et en rattrapant l'exception,


Est-elle réellement lancée ?

j'ai
toujours un arrêt du programme (et un coredump) sur la ligne
d'allocation mémoire.


Quel est le code des constructeurs ? En faisant si peu
d'allocations, je ne vois pas à priori où le problème pourrait se
situer d'autre que dans un constructeur (éventuellement d'une variable
membre).

--drkm

Avatar
Loïc Joly
Gaël Jaffré wrote:


#define SIGN_NB_VAL_MAX 64


Une constante serait AMA plus appropriée.
int const SIGN_NB_VAL_MAX = 64;

class Signature
{
public:
inline Signature(void);
inline Signature(IplImage *im_segmentee);
inline ~Signature(void);
void remplir(IplImage *im_segmentee);
void remplir_completement(IplImage *im_segmentee);
void afficher(void) const;
inline int operator ==(Signature & s2) const;
inline Signature & operator =(const Signature & s);
friend inline double mesure_similarite(const Signature *s1, const
Signature *s2);

private:
couleur couleurs[SIGN_NB_VAL_MAX];
int nb_occ[SIGN_NB_VAL_MAX];
double frequences[SIGN_NB_VAL_MAX];
CvMat *matrice;


La classe Signature est-elle propriétaire de matrice (est-ce que c'est
une signature qui est sensée appeler le new et le delete de ce pointeur)
? si oui, je vois un problème dans la classe : Il lui manque :
- Soit un constructeur par copie défini comme il faut
- Soit la désactivation du constructeur par copie généré par défaut (on
le déclare en privé, on ne le définit pas).

Souvent, lorsque l'on se trouve à définir de façon différente de la
version par défaut l'un des trois parmi {constructeur de copie,
opérateur=, destructeur}, il faut aussi définire les deux autres.

int nb_couleurs;
int nb_pixels;
CvMat *mat_signature(void);
};



--
Loïc

Avatar
Gaël Jaffré
Mais même en testant les 2 cas, et en rattrapant l'exception,



Est-elle réellement lancée ?


Non, justement, elle n'est pas lancée, le coredump est généré avant.


Quel est le code des constructeurs ? En faisant si peu
d'allocations, je ne vois pas à priori où le problème pourrait se
situer d'autre que dans un constructeur (éventuellement d'une variable
membre).


Je n'ai aucun objet dans mes variables membres, juste des structures,
donc je n'ai aucun autre appel de constructeur.
Le programme s'arrête avant même l'appel du constructeur, car
l'affichage (1ère ligne) ne se fait même pas.


inline Signature::Signature(void)
{
printf("__Construction__n");
this->nb_couleurs = 0;
this->nb_pixels = 0;
this->matrice = NULL;
}


Avatar
Gaël Jaffré
La classe Signature est-elle propriétaire de matrice (est-ce que c'est
une signature qui est sensée appeler le new et le delete de ce pointeur)


matrice n'est pas une classe, mais une structure, donc il n'y a pas de
new et de delete, mais des malloc/free.


? si oui, je vois un problème dans la classe : Il lui manque :
- Soit un constructeur par copie défini comme il faut
- Soit la désactivation du constructeur par copie généré par défaut (on
le déclare en privé, on ne le définit pas).



Je ne comprends pas trop en quoi à quoi est-ce que le constructeur par
copie va servir dans ce cas ? J'utilise des références dans toutes les
fonctions, donc je pensais que le constructeur pas copie ne serait
jamais appelé.

Avatar
Fabien LE LEZ
On Tue, 18 May 2004 10:37:13 +0200, Gaël Jaffré
wrote:

Le programme s'arrête avant même l'appel du constructeur, car
l'affichage (1ère ligne) ne se fait même pas.


Il se peut que la sortie standard soit bufferisée, et que le programme
plante avant que les données à afficher aillent du buffer à l'écran.
C'est d'ailleurs pour éviter ça que "endl" existe...

Toutefois, il y a effectivement de grosses chances pour que la raison
du core dump soit avant la création de cet objet.

inline


A quoi sert-il ?

Signature::Signature(void)


le "void" pour indiquer l'absence d'argument, même s'il est accepté
par le langage C++, c'est plutôt du C. Tout comme printf, d'ailleurs,
même si on peut peut-être laisser passer ici vu que c'est juste du
débogage.

{
printf("__Construction__n");
this->nb_couleurs = 0;


Le "this->" est inutile, il ne sert qu'à alourdir le code et à le
rendre moins lisible (ce qui est peut-être le but).

this->nb_pixels = 0;

this->matrice = NULL;


Mmm... "NULL", ça signifie qu'il y a un pointeur quelque part, donc
mémoire allouée "à la main", donc emplacement possible pour un core
dump. Vraisemblablement pas celui qui nous occupe, mais fais quand
même particulièrement attention.

}


En C++, on écrit généralement un constructeur sous cette forme :

Signature::Signature()
: nb_couleurs (0)
, nb_pixels (0)
, matrice (NULL) /* Note ici : s'il y avait de l'allocation
dynamique, je la mettrais à l'intérieur des accolades. */
{
std::cout << "__Construction__" << endl;
}


--
;-)
FLL, Epagneul Breton

Avatar
Christophe de VIENNE
Gaël Jaffré wrote:

matrice n'est pas une classe, mais une structure, donc il n'y a pas de
new et de delete, mais des malloc/free.



classes et structures sont identiques en C++. Et mélanger l'usage de
new/delete et malloc/free n'est pas tellement conseillé.
Donc pour matrice utilise de préférence new/delete.


? si oui, je vois un problème dans la classe : Il lui manque :
- Soit un constructeur par copie défini comme il faut
- Soit la désactivation du constructeur par copie généré par défaut
(on le déclare en privé, on ne le définit pas).



Je ne comprends pas trop en quoi à quoi est-ce que le constructeur par
copie va servir dans ce cas ? J'utilise des références dans toutes les
fonctions, donc je pensais que le constructeur pas copie ne serait
jamais appelé.


Il n'est jamais appelé ou bien il ne doit jamais être appelé ?
Quoi qu'il en soit la désactivation du constructeur par copie permet de
s'en assurer.

--
Christophe


Avatar
kanze
drkm wrote in message
news:...
Gaël Jaffré writes:

Mais même en testant les 2 cas, et en rattrapant l'exception,


Est-elle réellement lancée ?


Il a parlé d'un problème au bout de deux ou trois allocations. Je doute
réelement qu'il ait épuisé toute le mémoire disponible aussi vite.

Comme a dit quelqu'un d'autre, ce genre de problème est généralement dû
à la corruption de l'espace de mémoire libre. S'il écrit au délà de la
fin de son objet, par exemple, on a affaire à un comportement indéfini ;
selon l'implémentation, il pourrait avoir des core avec des objets sur
la pile, et non sur le tas, ou vice versa, ou des core avec les deux, ou
ni avec l'un ni avec l'autre. C'est toujours dans cette direction-là que
je chercherai.

L'autre possibilité, c'est comme a dit Loïc, qu'il manque un
constructeur de copie, et qu'il finit par libérer la matrice deux
fois. Je ne vois pas a priori d'où viendrait la différence entre
l'allocation sur la pile et l'allocation dynamique, mais c'est possible.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


1 2 3