Pb Qt + librairies C

Fermé
Sya - 7 févr. 2012 à 15:30
mamiemando Messages postés 33410 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 2 décembre 2024 - 13 févr. 2012 à 19:43
Bonjour,

Je suis sous Ubuntu 11.10 et j'ai un programme Qt qui n'arrive pas à s'executer
La compilation se passe bien mais à l'execution j'ai le fameux "segmentation fault".
Et ça n'est pas tout, j'ai parcouru le programme et j'ai remarqué qu'il ne prenait pas en considération les librairies C, juste celles specifiques à Qt. Lorsque le curseur est sur #include <stdio.h> par exemple il me dit aucun fichier ou repertoire de ce type mais pas d'erreurs à la compilation!
et d'aprés quelques tests, j'ai decouvert que l'erreur provenait d'une boucle que voici:
if (strcmp(chaine, "") != 0) {
            i = 1;
            while (etat != ',') {
                etat = fgetc(grille);
                chaine[i] = etat;
                i++;
            }
            chaine[i] = '\0';
            numero = strtol (chaine, NULL, 10);
        }

avec char chaine[4], etat; int i; et le compte ne commence pas par 1, il y a tout un traitement pour le premier caractère (0).

Je ne pense pas qu'il y est des erreurs la dedans! en tout cas lorsque je la met en commentaires (la boucle entière) ça marche!
Donc je me disais qu'il ne reconnaissais pas le type chaine de caractère à cause des includes ou je ne sais pas....
Que ce que vous en dites? quelqu'un a-t-il une idée?
Merci!

A voir également:

15 réponses

mamiemando Messages postés 33410 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 2 décembre 2024 7 808
Modifié par mamiemando le 7/02/2012 à 20:23
C'est normal, en C++ on n'inclue pas de headers "C" ou pas comme ça. Normalement tu dois inclure <cstdlib> au lieu de <stdlib.h>, <cstdio> au lieu de <stdio.h> etc...

Si ce n'est pas un header standard (genre un header C que tu as écrit toi même), tu n'auras pas possibilité de t'en sortir comme ça. Il faut alors faire l'inclusion comme suit :

extern "C" { 

#include "mon_header1.h" 
#include "mon_header2.h" 

}


De manière générale, je ne pense pas que tu aies forcément besoin de stdio, en C++ on utiliserait plutôt les iostreams et les opérateurs associés (<< et >>). Dis-moi ce que tu veux faire pour plus de précisions.

Par rapport à ton erreur regardons le code :

while (etat != ',') { 
  etat = fgetc(grille); 
  chaine[i] = etat; 
  i++; 
}


Je te rappelle qu'en C, la chaine de caract-ère "bonjour" est stocké sous la forme de 8 caractères (7 lettres et le caractère d'arrêt, '\0') :

 'b' 'o' 'n' 'j' 'o' 'u' 'r' '\0'


Dans ta boucle on avance dans la chaîne "chaine", mais rien ne garantit qu'on ne va pas en sortir. Par ailleurs je ne sais pas si c'est voulu, mais vu que i est initialisé à 1 (et non à 0) tu ne vas pas évaluer le premier caractère de chaîne.

Et c'est ce qui se passe. Si tu itères par exemple 10 fois mais que la chaîne est de longueur 3, et bien tu débordes à la 4e itération. Il faudrait que la boucle while s'arrête si on atteint chaine[i] == '\0', ce qui équivaut à tester si chaine[i] est non nul, ce qu'on peut écrire en C directement par :

if (chaine[i]) {
// ok, on n'a pas atteint le bout de la chaîne !
}else{
// on atteint le caractère \0 qui arrête la chaine
}

J'en profite pour rappeler que la notation chaine[i] signifie en C le caractère positionné en mémoire i octets * sizeof(char) après l'adresse stockée dans chaine (puisque chaine est de type char *). Si ce n'est pas évident pour toi, je t'invite à lire un cours sur les pointeurs et les tableaux. Partant de là autant décaler un pointeur d'un caractère à chaque itération (le code sera plus performant, et c'est comme ça que la boucle sera écrite par quelqu'un qui code bien en C).

Ainsi ta boucle devient :

while(*pchar++ && etat != ',') { 
  pchar = etat = fgetc(grille); 
}


Ici la boucle est interrompue dès qu'on arrive à la fin de chaine (car *pchar == '\0' <=> *pchar va interrompre la boucle). Note qu'on a directement integré le décalage du pointeur dans le while grâce à ++.

Bon mais de toute façon, vu que le but est d'extraire des valeurs numérique séparées par des ',', il serait plus logique d'utiliser la fonction strtok si on devait écrire en C :
http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man3/strtok.3.html

En C++, on ne s'embêterait même pas autant que ça. On utiliserait par exemple directement l'objet std::string (sans doute que les QString de Qt permettent de faire des choses similaires d'ailleurs). Plus besoin des fonctions de <string.h> (<cstring>) comme strcmp, on peut directement utiliser les opérateurs =, <, > (chose qu'on ne pourrait pas faire avec des char *, car sinon on comparerait leur adresse mémoire). Plus besoin non plus de se préocupper des allocations mémoires (et donc des risques de segmentation fault), les std::string se comportent comme des chaînes de longueurs virtuellement infinies.

#include <string> 
#include <iostream> 
#include <cstdlib> 

int main(){ 
    const std::string s = "12,34,567"; 
    if (s != "") { 
        std::string substring; 
        std::size_t begin = 0, end; 
        do { 
            end = s.find(',', begin); 
            substring.assign(s, begin, end - begin); 
            long l = atol(substring.c_str()); 
            std::cout << "l = " << l << std::endl; 
            begin = end + 1; 
        } while(end != std::string::npos); 
    } 
    return 0; 
}


ce qui donne :

(mando@aldur) (~) $ g++ plop.cpp && ./a.out  
l = 12 
l = 34 
l = 567


Note : tu peux utiliser strtol et ainsi contrôler qu'il y avait bien une valeur numérique à récupérer, sinon autant utiliser atol...

Bonne chance
0
Bonjour,

Merci pour votre reponse! Mais...
Pour les inclusions ça ne marche pas même en essayant <cstdio> au lieu de <stdio.h> et même chose pour <iostream>! seules les headers specifiques à Qt sont reconnus!

Pour la taille de la chaine, c'est voulu (le nombre est sur 1, 2 ou 3 positions maximum)
Et le compte ne commence pas par 1:
Dans le fichier un caractère est lu: si c'est une lettre un traitement specifique est effectué sinon si c'est un chiffre la boucle du dessus sera executée.
0
mamiemando Messages postés 33410 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 2 décembre 2024 7 808
8 févr. 2012 à 10:06
Pour les inclusions ça ne marche pas même en essayant <cstdio> au lieu de <stdio.h> et même chose pour <iostream>! seules les headers specifiques à Qt sont reconnus!

Je ne sais pas comment ta machine est installée ni quelles options de compilation du passe. Mais normalement si tu compiles avec g++ et que tu es sous linux il devrait les trouver... Peut-être les histoires de qmake etc... je ne me souviens plus trop de Qt.

Au pire tu utilises les classes Qt (Qstring et autres).

Pour la taille de la chaine, c'est voulu (le nombre est sur 1, 2 ou 3 positions maximum)

Même si c'est voulu, c'est un programme a priori peu robuste et qui peut planter en fonction de ses données d'entrée. La moindre des choses c'est de rattraper ce genre d'erreur ou de s'assurer en pré-condition qu'elle ne peut arriver. Et là elle arrive ;-)

Et le compte ne commence pas par 1:

Je te parle de la valeur de i, je ne sais pas si on parle de la même chose. Car là concrètement tu n'exploites pas dans cette section de code chaine[0]. Si c'est voulu, alors pas de soucis !

Bonne chance
0
Je ne compile pas avec g++ c'est l'environnement Qt qui le fait (j'utilise Qt Creator) sinon manuellement je fait:
qmake -project nom_projet
qmake
make
nom_projet (pour exécuter)


Pour la robustesse du programme: je ne crois pas que limiter une chaîne à une condition qui vraiment ne peut arriver pose problème (la condition: le nombre d'obstacles dans un environnement (déjà 3 positions c'est trop alors là plusieurs... mais pour plus de surete j'ai mis 3)

la valeur de i... je ne comprend pas ce que vous voulez dire, j'ai écrit:
" Dans le fichier un caractère est lu: si c'est une lettre un traitement specifique est effectué sinon si c'est un chiffre la boucle du dessus sera exécutée. "

si c'est un chiffre: ce dernier sera stocké dans chaîne[0] et après la boucle sera exécuté, oui peut être qu'il fallait être plus précis!
0

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

Posez votre question
mamiemando Messages postés 33410 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 2 décembre 2024 7 808
8 févr. 2012 à 10:37
Ok donc en fait de mémoire qmake cert à générer un makefile qu'ensuite tu invoques avec make. Tu peux donc regarder dans ce makefile ce qui est utilisé pour compiler.

Pour la robustesse du programme: je ne crois pas que limiter une chaîne à une condition qui vraiment ne peut arriver pose problème (la condition: le nombre d'obstacles dans un environnement (déjà 3 positions c'est trop alors là plusieurs... mais pour plus de surete j'ai mis 3)

En fait je voulais dire, il faut éviter d'écrire une boucle qui est susceptible de planter si certains paramètres qu'elle reçoit peut déclencher une erreur mémoire. Typiquement contrôler l'existence de pchar en parcourant une char * de gauche à droite (en imaginant qu'il ait été initialisé par une chaîne de caractère) permet d'éviter de dépasser la taille de cette chaîne.

si c'est un chiffre: ce dernier sera stocké dans chaîne[0] et après la boucle sera exécuté, oui peut être qu'il fallait être plus précis!

Disons que je ne sais pas ce que fait exactement ton programme, mais si tu es sûr(e) de ce que tu fais, laisse comme c'est :-) Ce que tu appelles chaîne c'est ce que j'ai appelé "s" dans la version c++. Si dans ton cas le premier caractère a un rôle particulier alors, effectivement c'est peut-être normal... Regarde avec un debugger si ton code fait ce que tu crois qu'il est fait :-)

Bonne chance
0
j'ai vu le fichier Makefile et je ne sais pas si le problème des includes a avoir avec la ligne
INCPATH       = -I/usr/share/qt4/mkspecs/linux-g++-64 -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I.

et la compilation se fait avec g++.
0
J'ai essayé d'ajouter -I/usr/include/c++/4.6 à la liste du dessus (INCPATH) et voilà ce qui s'est affiché aprés compilation:
parse error at "std"
Fichier non trouvé: usr/include/c++/4.6/bits/stringfwd 

Je suis allé voir dans le repertoire spécifé et il y avait le fichier "stringfwd.h" et non "stringfwd" alors je ne sais plus si mon idée du départ était fausse ou .......
0
mamiemando Messages postés 33410 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 2 décembre 2024 7 808
Modifié par mamiemando le 10/02/2012 à 19:57
Si tu as ajouté -I/usr/include/c++/4.6 tu devrais alors pouvoir inclure /usr/include/c++/4.6 avec un "#include <string>", ce qui inclue en réalité /usr/include/c++/4.6/string. Note que ce header n'a pas d'extension ".h", et c'est pour cela qu'on inclue <string> et non <string.h> (accessoirement, ça évite les ambiguïtés avec la libc, qui elle stocke ses headers dans /usr/include)

/usr/include/c++/4.6/string inclue <bits/stringfwd.h>, ce qui a un sens puisque le fichier en question s'appelle en réalité "/usr/include/c++/4.6/bits/stringfwd.h". Je ne sais pas si c'était ta question.

Par contre, je me demande comment tu as installé Qt, mais je commence à m'interroger. A priori la librairie Qt s'installe via les paquets, typiquement avec une commande du genre :

sudo apt-get install libqt4-dev


Est-ce comme ça que tu as procédé ?

Bonne chance
0
pour l'installation, je l'ai fait depuis logithèque ubuntu en sélectionnant Qt Creator.

Et même si j'ai changé le nom du header le problème est resté tel quel!
0
mamiemando Messages postés 33410 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 2 décembre 2024 7 808
12 févr. 2012 à 13:48
Mmmmh... Essaye d'installer le paquet que je t'ai indiqué. Surtout ne change pas les fichiers fournis par les paquets, car à la prochaine mise à jour, toutes tes corrections seront perdues (et accessoirement, ton programme ne pourra être compilé que sur ta propre machine).

Éventuellement mets les sources de ton programme en partage par exemple sur easyshare et j'essaierai de voir si j'arrive à les compiler.

Bonne chance
0
en essayant
sudo apt-get install libqt4-dev

j'ai:
Lecture des listes de paquets... Fait
Construction de l'arbre des dépendances       
Lecture des informations d'état... Fait
libqt4-dev est déjà la plus récente version disponible.
libqt4-dev passé en « installé manuellement ».
0 mis à jour, 0 nouvellement installés, 0 à enlever et 9 non mis à jour.
0
Utilisateur anonyme
12 févr. 2012 à 17:07
Salut,

Il y a longtemps que j'ai tourné sous Ubuntu, donc je ne me souviens plus s'il est possible d'installer gcc/g++ sans installer build-essantial. Si c'est le cas, tu ne pourras pas include string, iostream et autre, car il ne seront pas présent sur ta machine.

Essai de faire :
 sudo apt-get install build-essential


@++ :- )
0
build-essential est déjà installé!
Et puis les programmes c/c++ se compilent normalement c'est juste sous Qt que ça ne marche pas!
0
mamiemando Messages postés 33410 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 2 décembre 2024 7 808
Modifié par mamiemando le 13/02/2012 à 10:22
De toutes façons, si tu arrives par ailleurs à compiler des programmes c++ qui mettent en jeu ces headers, c'est clairement la manière dont tu compiles ton projet qui est cause du problème. Intuitivement j'aurais rajouté l'option -I/usr/include/c++/4.6 et en incluant <string>... Mais apparemment c'est plus subtil et en plus on sent que c'est pas top le jour où on va changer de version de g++.

Ici, le tutoriel explique qu'il faut passer l'option CONFIG += stl à qmake :
http://www.siteduzero.com/tutoriel-3-38269-compiler-facilement-qt.html

Bonne chance
0
Il n'y a pas l'équivalent de <sys/ipc.h> et <sys/sem.h> en c++ ? parce que ces fichiers sont inclus aussi dans le projet et je me demande si l'erreur ne vient pas d'eux après correction de <string> ?
Et ça ne marche pas après rajout de
CONFIG += stl au fichier .pro
0
mamiemando Messages postés 33410 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 2 décembre 2024 7 808
Modifié par mamiemando le 13/02/2012 à 19:45
Je ne pense pas que ça existe en c++, et si tu veux inclure des headers c dans un projet c++, tu es sensé les inclure comme suit :

extern "C" { 

#include <sys/ipc.h> 
#include <sys/sem.h> 

}


Par contre, je ne vois pas le rapport avec le header <string>, qui ne dépend que de headers c++ (qui sont dans /usr/include/c++ et non de fichiers dans /usr/include/x86_64-linux-gnu/sys, dans lequel figure sem.h). À voir si ensuite, dans qmake, ajouter ce chemin requiert une option spécifique...

Bonne chance
0