probleme inexplicable

thesuixx
probleme inexplicable

salut, je debute en c et je viens de passer 3 heures à essayer de trouver une erreur dans une fonction.
Quelqu'un sait où est l'erreur:

/**
*renvoie un string de la forme "num=\"0n\"" ou nh est le numero de la zone
* @param nomFicJourn: le nom du fichier journal
* @return un string de la forme "num=\"0n\"" ou nh est le numero de la zone
*/
char* nomJournalToNumZone(char nomFicJourn[]){
	printf("nomFicJournal %s\n",nomFicJourn);
	fflush(stdout);
	
	int i = 0, cptNumJourn = 5;
	char *positioneurDeb, *positioneurFin, *copieFicJourn;

	copieFicJourn = (char*) calloc(strlen(nomFicJourn), sizeof(char));
	strcpy(copieFicJourn, nomFicJourn);
	
	numJournal = "num=\"00\"";

	if (strstr(copieFicJourn,PREFIX_FIC_JOURN) != NULL && strstr(copieFicJourn,SEPARATEUR_FIC_JOURN) != NULL){
		positioneurDeb = strstr(copieFicJourn,PREFIX_FIC_JOURN)+sizeof(char);  // on se place apres le prefix
		positioneurFin = strstr(copieFicJourn,SEPARATEUR_FIC_JOURN);  // on se place sur le separateur "-"

		while (i < positioneurFin - positioneurDeb){
			printf("debJournal : %d , valeur = %c \n",nomFicJourn, *nomFicJourn);
			printf("copieFicJourn : %d , valeur = %c \n",copieFicJourn, *copieFicJourn);
			printf("positioneurDeb : %d , valeur = %c \n",positioneurDeb, *positioneurDeb);
			printf("positioneurFin : %d , valeur = %c \n",positioneurFin, *positioneurFin);
			printf("strlen = %d , journal = %s \n", strlen(numJournal), numJournal);
			printf("numJournal[cptNumJourn + i] : %c \n ",numJournal[cptNumJourn + i]);
			printf("indnumJournal : %d \n", cptNumJourn +i);
			printf("*(positioneurDeb + i) : %c \n" , *(positioneurDeb + i));
			
			fflush(stdout);
			numJournal[cptNumJourn + i] = *(positioneurDeb + i);
			i++;
		}
	}
	printf("%s \n", numJournal);
	fflush(stdout);
	printf("nomFicJournal %s\n",copieFicJourn);
	fflush(stdout);
	return numJournal;
}

et voici le resultat:
nomFicJournal j04-19940921.xml
debJournal : 4215072 , valeur = j
copieFicJourn : 6686608 , valeur = j
positioneurDeb : 6686609 , valeur = 0
positioneurFin : 6686611 , valeur = -
strlen = 8 , journal = num="00"
numJournal[cptNumJourn + i] : 0
 indnumJournal : 5
*(positioneurDeb + i) : 0
      8 [main] passerelle 2912 _cygtls::handle_exceptions: Error while dumping s
tate (probably corrupted stack)
./lancer.sh: line 3:  2912 Segmentation fault      (core dumped) passerelle.exe
2 testCalamar/zonecalam.xml testCalamar/j04-19940921.xml res.bid

en sortie, je devrais avoir num="04" ( "num=\"04\"" ) , où 04 est la partie du nom de fichier j04-19940921 entre le j et le -

La declaration du tab:

char *numJournal; 

les define:
#define PREFIX_FIC_JOURN 		"j"   // la premiere lettre des fichiers journaux (choix d'un string pour modifications futures)
#define SEPARATEUR_FIC_JOURN 	"-"   // choix d'un string pour modif futures

voila, comme vous voyez, j'ai printé à peu pres tout mais je trouve toujours pas de probleme, si quelqu'un peut me dire où est le probleme ca serait super
merci d'avance
fredericmazue

Inexplicable dis tu ?
Que nenni ..
Ah la bonne vieille arithmétique de pointeurs. :lol:

Je n'ai pas lu attentivement ton code. Pas le temps ce soir :oops:
Peut être demain.
Mais en attendant voici les pistes à suivre.
On te dit que la pile est corrumpue. (probably corrupted stack)
A coup sûr ça veut dire que quand tu affectes numJournal[] tu as un débordement de tampon. Ce qui d'ailleurs saute au yeux:

numJournal = "num=\"00\""; 

Longueur 7
or
cptNumJourn = 5;

et i < positioneurFin - positioneurDeb
i doit bien valoir 3 au fil des incrémentations (je dis ça au pif remarque)

3 + 5 = 8 > 7

Dans le meilleur des cas tu écrases le zéro de fin de chaîne avec numJournal[cptNumJourn + i]

Ensuite, autre problème très classique

return numJournal;

Quelle horreur.. (pardonne moi, mais alors) quelle horreur

1 tu retournes une globale, ce qui n'a déjà pas de sens
2 tu retounes le pointeur certes, mais CE QU'IL pointe est sur la pile dans ta fonction nomJournalToNumZone donc ce qu'il pointe est détruit au retour de ta fonction. Donc même si mon ampéropifomètre se trompe plus haut à propos des indices de tableau , ton code ne peut en aucun cas marcher, à cause de ce return.

Tiens j'ose la question qui tue. (Ceux qui me connaisse sur ce fourm savent bien que je ne peux pas m'en empêcher ;) ) Avant de t'essayer à C, tu faisais du Java ?

thesuixx
euh... snif ?

1) pour la taille du tableau, tu te trompes je pense, le print me confirme que la taille est de 8
2) le return d'une variable globale est TRES moche je suis d'accord mais je l'ai laissé tel quel parce que ca me saoulait de devoir modifier l'appel de cette fonction. (je débute en c, pas en programmation)
3) le programme plante au premier tour de boucle quand i = 0, les print le confirment
4) et pour ton plaisir uniquement: oui je faisais du java avant ca :D

thesuixx

de plus, i ne depassera jamais 2 si le nom de fichier est correct. (voir print)

autre chose, pour etre sur de mon coup :

char *truc = "frgdr" ca equivaut bien à un calloc(5, sizeof(char)) avec remplissage du tableau, non ?

fredericmazue

Quote:
3) le programme plante au premier tour de boucle quand i = 0, les print le confirment

Pour l'indice correct ou pas, je ne sais pas. Comme je t'ai dit, je l'ai dit au pif, voyant le message de corruption de pile, très symptômatique du problème.
Si ça plante au premier tour, c'est qu'un pointeur ne pointe pas où il doit. Ce qui ne veut pas dire que plus loin d'autres erreurs ne t'attendent pas.
Quote:
le return d'une variable globale est TRES moche je suis d'accord

Au delà d'être moche, c'est une faute.

Quote:
char *truc = "frgdr" ca equivaut bien à un calloc(5, sizeof(char)) avec remplissage du tableau, non ?

Et bien non pas du tout. Pas de calloc ici. Les octets frgdr sont empilés dans la pile et truc est initialisé pour pointer dessus. Au retour de la fonction la pile est détruite et les octcts frdrg aussi, et le pointeur continue de pointer au même endroit, c'est à dire n'importe quoi.
On est en C, pas en Java ;)

Quote:
4) et pour ton plaisir uniquement: oui je faisais du java avant ca

Ce n'est pas vraiment mon plaisir, bien au contraire. Je pense que quand on enseigne (ou demande de pratiquer ) Java avant C, on commet un crime contre l'humanité informatique.
Et le "return" dans ton code dit bien ce qu'il veut dire: tu as été enduit d'erreur à l'insu de ton plein gré. :(
thesuixx

Et bien non pas du tout. Pas de calloc ici. Les octets frgdr sont empilés dans la pile et truc est initialisé pour pointer dessus. Au retour de la fonction la pile est détruite et les octcts frdrg aussi, et le pointeur continue de pointer au même endroit, c'est à dire n'importe quoi. 

je vais faire un calloc pour mon tableau dans le header alors, ca devrait resoudre le probleme (sinon je reviendrai pour t'embeter avec mon ignorance du c :P). En tout cas merci beaucoup pour ton aide et:

- encore une fois, je t'assure que le return c'était par pure flemme (je suis débutant en c mais ya des limites)
- et je n'ai pas commencé la prog avec java non plus

fredericmazue

Quote:
sinon je reviendrai pour t'embeter

Oui avec plaisir.
Au fait, tu es obligé de faire en C, parce qu'en C++ avec la classe string ça serait infiniment plus facile.
Quote:
et je n'ai pas commencé la prog avec java non plus

Basic ? ;)
thesuixx

non, ADA ... :S

Non, malheureusement je dois le faire en C vu que cette méthode et bien d'autres vont être ajoutés à un gros programme deja existant en C.

fredericmazue

Quote:
je vais faire un calloc pour mon tableau dans le header alors, ca devrait resoudre le probleme

De la façon dont tu le dis je crains que tu n'ajoutes une erreur. Essaie et si ça ne va pas reviens nous voir.
Sinon tu as l'air de coder pour Linux/Gygwin. Dans ce cas tu as peut être le droit d'utiliser la glib (à ne pas confondre avec glibc) qui est la fondation de Gtk. Dans la glib tu vas trouver plein de fonctions pour travailler avec les chaines en C
thesuixx

ca y est j'ai reussi à regler mon probleme, c'était bien une histoire de calloc on dirait

/**
*renvoie un string de la forme "num=\"0n\"" ou nh est le numero de la zone
* @param nomFicJourn: le nom du fichier journal
* @return un string de la forme "num=\"0n\"" ou nh est le numero de la zone
*/
int nomJournalToNumZone(char *nomFicJourn){
	printf("nomFicJournal %s\n",nomFicJourn);
	fflush(stdout);
	
	int i = 0, cptNumJourn = 5;
	char *positioneurDeb, *positioneurFin, *copieFicJourn;

	if (strstr(nomFicJourn,PREFIX_FIC_JOURN) != NULL && strstr(nomFicJourn,SEPARATEUR_FIC_JOURN) != NULL){
		positioneurDeb = strstr(nomFicJourn,PREFIX_FIC_JOURN)+sizeof(char);  // on se place apres le prefix
		positioneurFin = strstr(nomFicJourn,SEPARATEUR_FIC_JOURN);  // on se place sur le separateur "-"

		while (i < positioneurFin - positioneurDeb){
			numJournal[cptNumJourn + i] = *(positioneurDeb + i);
			i++;
		}
	}
	printf("%s \n", numJournal);
	fflush(stdout);
	return 0;
}

et l'appel de la fonction

numJournal = calloc(9, sizeof(char));
	numJournal[0] = 'n';
	numJournal[1] = 'u';
	numJournal[2] = 'm';
	numJournal[3] = '=';
	numJournal[4] = '\"';
	numJournal[5] = '0';
	numJournal[6] = '0';
	numJournal[7] = '\"';
	numJournal[8] = '\0';

	nomJournalToNumZone(nomFicJournal);

ca fait beaucoup de lignes pour pas grand chose mais ca a l'air de marcher.

Avant ca, j'avais fait:

numJournal="num=\"00\"";
nomJournalToNumZone(nomFicJournal);

mais ca semblait poser probleme

tu as l'air de coder pour Linux/Gygwin

Affirmatif :P
fredericmazue

Quote:
c'était bien une histoire de calloc on dirait

Je ne dirais pas ça comme ça. C'était un problème de pointeur et de données invalidées sur la pile. Pas besoin de calloc en fait. Il suffit de délcarer ta globale ainsi:

char *numJournal = "num=\"00\"";

Par contre avec calloc, tu dois libérer la mémoire allouée avec free ;)

Quote:
ca fait beaucoup de lignes pour pas grand chose

C'est un problème inhérent à C qui est un langage de très bas niveau. C'est pour cas que l'usage de la glib est souvent fort pertinent pour éviter d'écrire des tombereaux de code, ou pour éviter d'écrire et ré-écrire mille fois le même code.