EDIT
Attention, ma réponse est fausse. Passez votre chemin. Vous êtes prévenus.
En lisant bien le code de smprintf, de bas en haut (si si) :
Et buf est défini comme ça :
Autrement dit, buf est un pointeur comme dans tous les bidule *truc en C, truc est un pointeur, un nombre qui représente le lieu pour trouver le contenu *truc de type bidule.
Quand tu écris :
Tu demandes à return de renvoyer un contenu et non pas un lieu. D’où l’erreur.
Tu demandes à return de renvoyer un contenu et non pas un lieu. D’où l’erreur.[/quote]
Autant je sais pas pourquoi son code plante autant ta réponse est fausse. Les chaines entre " sont des pointeurs sur char, donc ça reste des pointeurs, d’ailleurs mon exemple montre bien qu’il n’y a pas de cast implicite de fait :
int main(void) {
printf(« %s\n », foo());
return EXIT_SUCCESS;
}
% CFLAGS=« -Wall -pedantic -Wextra -Wreturn-type -Wconversion » make -B coucou
cc -Wall -pedantic -Wextra -Wreturn-type -Wconversion coucou.c -o coucou
% ./coucou
Hello world !!![/code]
On peut plus se poser la question de savoir vers quoi point ce pointeur et si ce n’est pas vers le tas qui serait alors nettoyé à la sortie de la fonction, mais si c’était le cas mon exemple ne marcherais pas.
Je me disais aussi…
Avec une chaîne vide, c’est que j’ai tenté en premier, mais ce n’est pas mieux.
Du coup, pour réinitialiser une chaîne, je fais par défaut :
Attend tu parle d’autre chose là d’un coup. Tu nous explique que tu veut renvoyer une chaine dans ton premier message et là tu parle de réinitialisée (avec une méthode assez moyenne).
Ben si, je t’ai donné un lien au dessus. Le programme je l’ai modifié pour qu’il marche tant bien que mal, mais l’erreur de segmentation je ne la pige pas.
...
dwmstatus.c:15:24: fatal error: mpd/client.h: Aucun fichier ou dossier de ce type
16% [alex:/tmp/test/dwmstatus]./dwmstatus
./dwmstatus: error while loading shared libraries: libmpdclient.so.2: cannot open shared object file: No such file or directory
[quote=“haleth”]
...
dwmstatus.c:15:24: fatal error: mpd/client.h: Aucun fichier ou dossier de ce type
16% [alex:/tmp/test/dwmstatus]./dwmstatus
./dwmstatus: error while loading shared libraries: libmpdclient.so.2: cannot open shared object file: No such file or directory
[/quote]
Eh oui, il faut les librairies pour mpd : libmpdclient-dev
Bouahp, j’ai honte, pas vu que c’était une lib hors projet …
Des trucs à redire:
ligne 45:
ln[strlen(ln)-1]=’\0’;
Tu cherches bien à supprimer le dernier caractère, et pas à insérer un \0 en bout de chaîne, oui ?
Les smprintf, tu dois free la valeur du retour (y’a plein de memleak en l’état)
Pour ton problème, y’a deux trucs à savoir;
Avec smprintf, tu renvoies un pointeur, donc le free(mpd) ligne 387 est OK;
Avec return("");, tu renvoies NULL, et le free(NULL) segfault;
Illustration (lignes à placer entre 386 et 387 par exemple):
[..]
printf("DEBUG: %i\n", mpd);
char* toto = "";
printf("DEBUG: %i\n", *toto);
[..]
1% [alex:/tmp/test/dwmstatus]./dwmstatus
fifo creation: File exists
mpd connection: Operation now in progress
DEBUG: 4204607
DEBUG: 0
Du coup, j’me demande pourquoi avec NULL il affiche (null), et avec “” il n’affiche rien. Ce devrait être identique, non ?
Crée un pointeur vers un caractère dont la valeur est 0 (‹ \0 ›).
Comme je le disais plus haut, je pense que c’est un problème de pile ou de tas.
Avec la syntaxe de mon second exemple, la chaine est sur la pile. Je ne sais pas sur quelle instruction le segfault apparaît mais sur la pile, tu ne peux pas libérer manuellement de la mémoire (donc free(ptr); avec ptr initialisé comme dans le secnd exemple va planter).
Cela sert à remplacer le retour à la ligne \n par le caractère de fin de chaîne.
Je croyais ne pas avoir oublié de free. À chaque fois je vais un return(smprintf(« %s »,chaine), et je libère à chaque cycle le contenu de la variable dans laquelle a été fait le retour. J’ai encore mal compris un truc…
Quand tu retournes une chaîne vide “”, tu ne retournes pas un char* alloué dynamiquement mais un const char* alloué statiquement. Deux différences :
tu ne peux pas modifier le contenu de la chaîne (const)
cette chaîne a été allouée statiquement lors de la compilation, donc il n’y a pas de mémoire à libérer car elle fait partie du binaire (section de données constantes, probablement protégées contre l’écriture si l’OS le permet). Si tu essayes malgré tout de la libérer, on tombe dans du Undefined Behaviour (UB) et là tout peut arriver (ça peut donner l’apparence de marcher, ça peut te donner une bête erreur de runtime, ça peut formater ton disque dur ou encore faire exploser la Lune, suivant ce que ton compilateur a choisi de faire)
Si ton API est censée te renvoyer une chaîne alloué dynamiquement (ie. en tant qu’utilisateur de l’API tu libères la chaîne plus tard avec free) alors tu ne dois pas renvoyer une chaîne statique car le free provoque l’UB.
La solution ? Allouer une chaîne dynamiquement et retourner ce pointeur.
char* chaine_vide = malloc(1);
chaine_vide[0] = 0; // null terminator pour indiquer une chaîne vide
return chaine_vide;
Et là t’es tranquille : tu peux free ta chaîne.
Selon la sémantique exacte de ton API, tu peux peut-être renvoyer un pointeur nul à la place (return 0;). Mais faut se méfier : des fois un pointeur nul et une chaîne vide veulent dire différentes choses donc c’est pas une solution générique…