IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Plantage si lancement depuis un terminal


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 28
    Points : 20
    Points
    20
    Par défaut Plantage si lancement depuis un terminal
    Bonsoir,

    En résumant, j'ai un programme qui prend en paramètre un nom de fichier (contenant plusieurs options utiles à son déroulement), et après moults calculs renvoie des prédictions de courbes en sortie de code de calcul.

    Ce que je trouve très étrange, c'est qu'il fonctionne très bien quand on hardcode le chemin du fichier dans le main.cpp : il ne prend alors plus aucun argument, et tourne parfaitement en renvoyant des résultats très plausibles. Que ce soit avec le compilo de Code::Blocks ou celui de Visual C++ Express. Par contre quand je le lance depuis un terminal (sous windows XP en ce moment), il crashe en m'indiquant une tentative d'accès à l'adresse 0x00000 =/

    J'ai isolé l'endroit qui plante, c'est un tout petit malloc, dans une librairie a priori fiable (SVM-light). ça doit donc venir de mon programme, mais je sais pas trop par où chercher..

    Piste: En lançant le programme avec un argument, il effectue un décalage de toutes les allocations mémoires car faut bien stocker argv[1]. Si mon programme comporte des utilisations de zones mémoires non affectées, ou des fuites mémoires ..etc, ça se ressentirait sans doute. Enfin c'est mon interprétation (n'expliquant pas que sur les quelques exemples que j'ai sous la main ça fonctionne très bien sans argument =/).

    Petites questions:
    - un bug "accès à 0x00000" en plein milieu de la fonction malloc, ça peut vouloir dire quoi ?
    - vous avez déjà eu ce genre de problème ? (si oui, résolu comment ? )

    Dès que je pourrai tester avec valgrind sous Linux je le fais (je viens juste de découvrir cet outil), et en attendant si vous avez d'autres idées elles sont les bienvenues :-)

    EDIT: en attendant j'ai testé avec la version d'évaluation d'IBM Rational Purify, il me trouve une vingtaine de memory leaks =/ Pas bon tout ça.. N'ayant pas trop envie de l'acheter, j'attends valgrind pour en savoir plus.

    Merci d'avance.

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 858
    Points : 218 577
    Points
    218 577
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    Je serai pas contre un morceau de code , de l'entrée du main , et de ta gestion des argument du main.
    Tu peux vérifier toi même ( avec un crayon est une feuille ) les memory leaks et les corriger en regardant les mallocs, et en vérifiant qu'il y a bien un free pour chaque malloc. Et dans tout les cas d'execution du programme.
    Bug au malloc tu passe pas les bons paramètres. Tu peux aussi vérifer si ton malloc fonctionne en verifant si ton pointeur fraichement alloué n'est pas égale à NULL

    Voilà comme premier conseil , que je puisse donner.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 28
    Points : 20
    Points
    20
    Par défaut
    Merci pour ta réponse,

    Cependant, tracer toutes les éventuelles erreurs mémoires serait long et fastidieux (y'a qd même pas mal de lignes, fichiers..). C'est pour ça que j'attendrai de récupérer mon PC sous Linux pour tester.

    "Bug au malloc tu passe pas les bons paramètres" : sisi, je connais quand même les paramètres de malloc ;-)
    "Tu peux aussi vérifer si ton malloc fonctionne en verifant si ton pointeur fraichement alloué n'est pas égale à NULL" : justement non, car le plantage s'effectue avant le retour du malloc (mais après l'entrée ^^). C'est un malloc du fichier svm_learn.c de Joachim Thorsten, et à première lecture y'a pas de bug apparent dedans (mais je n'ai pas relu toutes ses fonctions de 400 lignes, j'avoue )

    Morceau de code de l'entrée du main quand même :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    int main (int argc, char** argv) {
     
    	if (argc<=1) {
    		cerr << "error: provide a parameter file name <example.dat>" << endl;
    		exit(1);
    	}
     
    	char *fNameInTr=(char*)calloc(128,sizeof(char)),
            *fNameOutTr=(char*)calloc(128,sizeof(char)),
            *fNameInTe=(char*)calloc(128,sizeof(char)),
            *fNameOutTe=(char*)calloc(128,sizeof(char));
    	readGlobals(argv[1],fNameInTr,fNameOutTr,fNameInTe,fNameOutTe); // read all parameters
     
    	[...Avec utilisation des fNameXXYY ensuite pour récupérer les jeux de données]

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 28
    Points : 20
    Points
    20
    Par défaut
    Bon, j'ai du mal à attendre valgrind en fait ^^

    J'ai donc continué avec la version d'évaluation d'IBM rational purify, et ai fini par isoler quelques bouts de code qui sont selon lui des memory leaks. Seulement moi je ne vois pas en quoi ce sont des erreurs =/

    Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    for (int i=0; i<dimRed[indCl]; i++) {
    	double* newVectBasis=(double*)malloc(nbDisc*sizeof(double));
    	for (int j=nbDisc-1; j>=0; j--) newVectBasis[j]=basisMat[j][i];
    	// make this new basis function as positive as possible
    	int countNeg=0;
    	for (int j=nbDisc; j>=0; j--) {
    		if (newVectBasis[j]<0) countNeg++;
    	}
    	if (countNeg>nbDisc/2) {
    		for (int j=nbDisc; j>=0; j--) newVectBasis[j]=-newVectBasis[j];
    	}
    	baseFunc[indCl].push_back(newVectBasis);
    }
    Dès qu'il y a plus de deux passages dans la boucle, il m'indique un memory leak de 168*k octets (et 168 est exactement la valeur de la variable nbDisc dans ce cas.. coïncidence troublante ).

    Où est le problème avec cette boucle ?

  5. #5
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Salut,

    Il y a quelque part un free qui correspond à ce malloc ?

    (tu devrais poser les questions sur le langage C dans le forum sur le langage C, ici c'est pour le C++)

    MAT.

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,

    Malgré la présence de cerr, ce code est manifestement écrit principalement en C...

    une seule alternative s'offre donc à donc à toi:
    • Tu décide de coder en C réel, et tu remplace les cin, cout, cerr éventuels par l'équivalent C (*printf et consort), et nous déplaçons la question dans le forum adéquat
    • Tu décide de réellement coder en C++, et le meilleur conseil à te donner est alors de travailler de préférence avec les capacités offertes par le C++ (remplacer les *alloc par new ou new[], utilisation des *fstream, string et autre conteneurs, ...)
    En effet, bien que le C++ hérite du C et qu'il ne renie absolument pas ses origines, il faut vraiment prendre l'habitude, lorsque l'on travaille en C++, de préférer toute solution propre à ce langage plutôt qu'une solution issue de son "aïeul".

    Les solutions propres au C++ sont en effet généralement bien plus sécurisantes et facile à l'emploi que les solutions équivalentes issues du C
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 28
    Points : 20
    Points
    20
    Par défaut
    Ah oui c'est vrai que je n'ai jamais désalloué ces fonctions, je viens de le faire donc, et oui ça venait de là. Merci !

    Concernant la section, d'accord je migrerai vers le forum C si ça concerne à nouveau les fuites mémoires. En fait la seule chose que j'utilise exclusive au C ce sont les malloc/free; mais c'est vrai que mes questions ici ne portent que sur ça.

    EDIT: merci à koala aussi En fait j'ai souvent lu que mixer spécificités du C et du C++ était déconseillé, en effet. Mais j'aime bien mes malloc, alors je vais les débugger et les laisser je crois.

    Sinon pour répondre à ta supposition, le programme est écrit en C++ "fonctionnel" (aucune classe, mais avec les std::vector bien pratiques). C'est comme ça que je fais assez souvent, promis je changerai un jour ^^

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par Ulath0 Voir le message
    Ah oui c'est vrai que je n'ai jamais désalloué ces fonctions, je viens de le faire donc, et oui ça venait de là. Merci !

    Concernant la section, d'accord je migrerai vers le forum C si ça concerne à nouveau les fuites mémoires. En fait la seule chose que j'utilise exclusive au C ce sont les malloc/free; mais c'est vrai que mes questions ici ne portent que sur ça.

    EDIT: merci à koala aussi En fait j'ai souvent lu que mixer spécificités du C et du C++ était déconseillé, en effet. Mais j'aime bien mes malloc, alors je vais les débugger et les laisser je crois.

    Sinon pour répondre à ta supposition, le programme est écrit en C++ "fonctionnel" (aucune classe, mais avec les std::vector bien pratiques). C'est comme ça que je fais assez souvent, promis je changerai un jour ^^
    La première habitude à prendre si tu veux coder en C++ est celle d'utiliser new ou new[] et delete ou delete[] au lieu des malloc, calloc, realloc et free associé.

    En effet, bien que, au final, le résultat puisse paraître sensiblement similaire ("il ne s'agit que d'une allocation dynamique de la mémorie"), new fait plus de chose que *alloc, en appelant - entre autre - le constructeur de l'objet à créer, est plus sécurisant en lançant une exception en cas d'échec et est au final bien plus facile à l'emploi (au pire, tu n'a qu'à donner le nombre d'élément à allouer, plutôt que de t'amuser à devoir convertir dans le type adéquat un espace mémoire calculé sur le nombre de caractères qui sont nécessaire pour contenir le type en question).

    De la même manière, il est fortement déconseillé d'utiliser le transtypage ("cast") "C style"... Préfères-y, si tu n'a vraiment pas d'autre choix les *_cast<type>(variable), qui permettent une vérification de la possibilité de transtyper bien plus sécurisante.

    Tous ces conseils, et nous pourrions t'en donner une liste énorme dans le genre, n'ont en définitive qu'un seul objectif: te permettre de coder plus facilement et de manière plus sécurisante, et donc te permettre d'obtenir plus facilement quelque chose "de qualité"
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 28
    Points : 20
    Points
    20
    Par défaut
    Oui oui je comprends bien tout ça

    Je sais que new appelle le constructeur et génère une exception en cas d'échec, c'est d'ailleurs la raison pour laquelle je réserve malloc aux types de base, et new aux objets de type classe.

    Pour le cast, je ne l'utilise que pour les types de base également donc me permet la syntaxe du C (j'ai quand même le droit de faire "float a; double b=3.1+(double)a" et autres casts évidents hein ^^ [oui celui là j'imagine que le compilateur le fait tout seul, c'était pour l'exemple ])

    En revanche, si t'as un lien avec une liste rassemblant ces conseils et un tas d'autres que je ne connais pas encore, je suis preneur ^^

  10. #10
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par Ulath0 Voir le message
    Oui oui je comprends bien tout ça

    Je sais que new appelle le constructeur et génère une exception en cas d'échec, c'est d'ailleurs la raison pour laquelle je réserve malloc aux types de base, et new aux objets de type classe.
    Non, tu dois réserver les *alloc à... strictement rien, et utiliser new ou new[] de manière systématique.
    Pour le cast, je ne l'utilise que pour les types de base également donc me permet la syntaxe du C (j'ai quand même le droit de faire "float a; double b=3.1+(double)a" et autres casts évidents hein ^^ [oui celui là j'imagine que le compilateur le fait tout seul, c'était pour l'exemple ])
    Encore une fois, non...

    Le cast "C style doit impérativement être réservé à... du code C.

    En C++, tu dois utiliser les cast... C++
    En revanche, si t'as un lien avec une liste rassemblant ces conseils et un tas d'autres que je ne connais pas encore, je suis preneur ^^
    Effectue une recherche sur le forum, le problème est récurrent

    Comme les conseils sont sans doute épars, tu peux rechercher des termes tels que
    • chaine "C style"
    • tableau "C style"
    • Allocation dynamique
    • choix du conteneur
    • possibilité issue du C++

    Sans avoir effectué personnellement la recherche, je peux t'assurer que ce sont des termes suffisamment utilisés pour te permettre de retrouver l'ensemble des conseils généralement reliés
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 28
    Points : 20
    Points
    20
    Par défaut
    Je te trouve un peu rigide mais merci pour tout, je ferai mes recherches.

  12. #12
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par Ulath0 Voir le message
    Je te trouve un peu rigide mais merci pour tout, je ferai mes recherches.
    Et pourtant:

    Si tu commence à mélanger new et *alloc, tu va vite "perdre le fil" et finir par essayer de libérer par delete quelque chose alloué avec *alloc ou essayer de libérer par free quelque chose alloué avec new.

    Les deux cas sont aussi mauvais l'un que l'autre, et, pour éviter tout problème, une seule solution s'impose: il faut unifier la manière dont tu fais tes allocation dynamique, afin d'unifier la manière dont tu libère la mémoire dynamiquement allouée

    Pour ce qui est du transtypage, il faut déjà savoir qu'il est finalement très rare de devoir y recourir...:
    • Une classe dérivée peut sans problème être fournie à une fonction demandant une classe mère
    • le "downcast" (le fait d'essayer de transtyper une classe mère en une classe fille) mérite amplement d'être sécurisé (et peut souvent être le signe d'une erreur de conversion)
    • Les seuls cas où il soit indispensable de transtyper de char vers n'importe quoi, c'est si c'est destiné à la transmission réseau, ou si tu manipule des fichiers dits "binaires" (par opposition aux fichier "texte")
    • les *_cast du C++ apportent, non seulement, une sécurité accrue du transtypage (exception faite du reinterpret_cast), mais permettent en outre de repérer bien plus facilement l'endroit où ils sont effectué (tant lors d'une lecture que lors d'une recherche)
    • Si le fait de transtyper un élément non constant en un élément constant ne pose aucun problème, il faut réfléchir sérieusement avant d'envisager de transtyper un objet constant en un objet non constant


    Il n'y a donc que des inconvéniants à utiliser le cast "C style" lorsque tu code en C++

    Si je te parais "rigide" dis toi que les raisons qui m'incitent à te reprendre fermement le justifient parfaitement, et qu'il ne s'agit que de te donner de bonnes habitudes, adaptées aux réalités du langage
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Lancement d'un terminal à l'éxecution d'un .jar
    Par anadobes dans le forum Langage
    Réponses: 5
    Dernier message: 19/06/2007, 10h55
  2. [PHP-JS] Lancement depuis un poste client
    Par vileb29 dans le forum Langage
    Réponses: 1
    Dernier message: 02/02/2007, 14h28
  3. Réponses: 2
    Dernier message: 17/01/2007, 21h01
  4. Lancement Processus: plus lents depuis java / terminal
    Par Zapan dans le forum Général Java
    Réponses: 7
    Dernier message: 01/02/2006, 20h13
  5. Réponses: 7
    Dernier message: 20/08/2003, 10h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo