Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

warning: function returns address of local variable

65 réponses
Avatar
pere.noel
à la compile d'un ensemble de fonctions + main, j'ai le message de
warning :
function returns address of local variable
pour la fonction "target_path_normalize"

le but de cette fonction :
si j'ai en entrée :

target_path_checked =
////Users////yvon/./////////////////////work/C/../.headers
toto/CFArray.h

elle retourne ce path normalisé :
target_path_normalized = /Users/yvon/work/.headers toto/CFArray.h

cette fonction "marche" mais je me demande quel risque je prends en
laissant trainer ce warning

le contexte : avant l'utilisation de cette fonction, j'en utilise une
autre "target_path_check" qui retourne NULL si le path n'est pas absolu
et accessoirement supprime le "/" en fin de chaîne s'il existe.

--- target_path_normalize ---------------------------------------------
char* target_path_normalize(const char* target_path)
{
int trente_deux = 32; /* maximum de répertoires traversés */
int mille_vingt_quatre = 1024; /* taille maximum d'un path */
char p[mille_vingt_quatre]="";
char *q;
char *token;
const char needle[] = "/";
const char *dot = ".";
const char *dotdot = "..";
int j;
q = strdup(target_path);
j = 0;
char *pieces[trente_deux];
// initialisation des éléments du tableau à NULL
while(j < trente_deux) {
pieces[j] = NULL;
j++;
}

// démarrage du découpage de q (target_path)
token = strtok(q, needle);
j = 0;

// découpage de q (target_path)
while(token != NULL) {
// si ".." on décrémente j equivalent à cd ..
// si "." on ne fait rien
// si différent de ".." et de "." on enregistre token dans
pieces[j] et on incrémente j
if(strcmp(token, dotdot) == 0) {
j--;
} else if(strcmp(token, dot) != 0) {
pieces[j]=token;
j++;
}
token = strtok(NULL, needle);
}
j = 0;

// concaténation de "/" (needle) et de pieces[j] jusqu'à épuisement
(quand pieces[j] == NULL)
while(pieces[j] != NULL) {
strcat(p, needle);
strcat(p, pieces[j]);
j++;
}
return p;
}
-----------------------------------------------------------------------
donc c'est le "return p" qui pose pb à la compil mais pas à
l'utilisation.
--
une bévue

10 réponses

1 2 3 4 5
Avatar
JustMe
=?ISO-8859-1?Q?Une_bévue?= a écrit
à la compile d'un ensemble de fonctions + main, j'ai le message de
warning :
function returns address of local variable
pour la fonction "target_path_normalize"

le but de cette fonction :
si j'ai en entrée :

target_path_checked > ////Users////yvon/./////////////////////work/C/../.headers
toto/CFArray.h

elle retourne ce path normalisé :
target_path_normalized = /Users/yvon/work/.headers toto/CFArray.h

cette fonction "marche" mais je me demande quel risque je prends en
laissant trainer ce warning

-----------------------------------------------------------------------
donc c'est le "return p" qui pose pb à la compil mais pas à
l'utilisation.


Declare la variable p en static

Avatar
Harpo
Une bévue wrote:


à la compile d'un ensemble de fonctions + main, j'ai le message de
warning :
function returns address of local variable
pour la fonction "target_path_normalize"
(...)

cette fonction "marche" mais je me demande quel risque je prends en
laissant trainer ce warning


Cette fonction ne marche qu'en apparence.
En fait elle retourne l'adresse de quelque chose qui peut être
considérée comme n'existant plus. Le comportement est indéfini (ici on
dit souvent UB (undefined behaviour)).
Tu changes de version de compilateur, ça pourra ne pas marcher, si tu
intercales l'appel d'une autre fonction entre le moment ou ta fonction
retourne et celui où tu déréférence le pointeur, il y a de bonnes
chances que ça ne marche pas, i.e que tu aies des données fausses, que
tu ne t'en aperçoive pas tout de suite et/ou que tu passes du temps à
débugger.

donc c'est le "return p" qui pose pb à la compil mais pas à
l'utilisation.


Malheureusement les tests ne permettent pas toujours de voir ce genre
d'erreur.

--
http://patrick.davalan.free.fr/

Avatar
pere.noel
JustMe wrote:

Declare la variable p en static


merci mais là j'ai une erreur ))) :

~/work/C/essais/save_path_array_new%> cc -W -Wall -Wextra
-Wuninitialized -Wstrict-prototypes -Wmissing-prototypes -pedantic
-stdÉ9 -O2 -pipe -o save_path_array_new save_path_array_new.c
save_path_array_new.c: In function 'target_path_normalize':
save_path_array_new.c:66: error: storage size of 'p' isn't constant


j'ai juste changé :

const int dirs_nbr_max = 32; /* maximum de répertoires traversés */
const int path_size_max = 1024; /* taille maximum d'un path */
static char p[path_size_max];

pourquoi donc gcc me dit "storage size of 'p' isn't constant" alors que
j'ai :

const int path_size_max = 1024; /* taille maximum d'un path */
static char p[path_size_max];


bien sûr si je met :

static char p[1024];

=> ni warning ni erreur, donc ça signifie qu'une const int... n'est pas
vue comme une constante ???

je dois définir dans mon .h cette constante ???

en utilisant :
long path_max = pathconf("/", _PC_PATH_MAX);

???

si j'ajoute dans mon .h :
# define PATH_SIZE_MAX pathconf("/", _PC_PATH_MAX)

avec dans mon .c :
static char p[PATH_SIZE_MAX];

j'ai toujours le pb "'p' isn't constant"

alors que :
printf("%ldn", PATH_SIZE_MAX);

me donne bien 1024...
--
une bévue

Avatar
JustMe
=?ISO-8859-1?Q?Une_bévue?= a écrit
JustMe wrote:

Declare la variable p en static





Ah oui, merde la taille est variable

Bon ba dans ce cas malloc, free, toussa...


Avatar
pere.noel
Harpo wrote:

donc c'est le "return p" qui pose pb à la compil mais pas à
l'utilisation.


Malheureusement les tests ne permettent pas toujours de voir ce genre
d'erreur.


la solution avec static ne provoque plus de warning donc c'est bon, par
contre je n'arrive pas à faire :

static char p[PATH_SIZE_MAX]; (au lieu de static char p[1024]

mon PATH_SIZE_MAX étant défini dans le .h :
# define PATH_SIZE_MAX pathconf("/", _PC_PATH_MAX) // vaut 1024

gcc me dit (dans le cas p[PATH_SIZE_MAX]) :

error: storage size of 'p' isn't constant

???


--
une bévue


Avatar
Harpo
Une bévue wrote:

Harpo wrote:

donc c'est le "return p" qui pose pb à la compil mais pas à
l'utilisation.


Malheureusement les tests ne permettent pas toujours de voir ce genre
d'erreur.


la solution avec static ne provoque plus de warning donc c'est bon,
par contre je n'arrive pas à faire :

static char p[PATH_SIZE_MAX]; (au lieu de static char p[1024]

mon PATH_SIZE_MAX étant défini dans le .h :
# define PATH_SIZE_MAX pathconf("/", _PC_PATH_MAX) // vaut 1024

gcc me dit (dans le cas p[PATH_SIZE_MAX]) :

error: storage size of 'p' isn't constant


#define A B
fait remplacer 'A' par 'B'

Dans ton cas 'PATH_SIZE_MAX' par
'pathconf("/", _PC_PATH_MAX)'

tu as donc
static char p[pathconf("/", _PC_PATH_MAX)];
et pathconf(...) ne semble pas être une expression constante.

--
http://patrick.davalan.free.fr/



Avatar
pere.noel
Harpo wrote:


#define A B
fait remplacer 'A' par 'B'

Dans ton cas 'PATH_SIZE_MAX' par
'pathconf("/", _PC_PATH_MAX)'

tu as donc
static char p[pathconf("/", _PC_PATH_MAX)];
et pathconf(...) ne semble pas être une expression constante.


ouais j'en passe donc par calloc dans un petit bout d'essai :

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

# define PATH_SIZE_MAX pathconf("/", _PC_PATH_MAX)

int main(int argc, char **argv)
{
char *str1 = "Hello ";
char *str2 = "World";
char *str3;

str3 = (char *)calloc(PATH_SIZE_MAX, sizeof(char));

strcat(str3, str1);
strcat(str3, str2);

printf("str3: %sn", str3);

free(str3);

printf("str3: %sn", str3);
return 0;
}

alors là, ce que je ne pige pas c'est qu'après "free(str3);" le
"printf("str3: %sn", str3);" donne le m^me résultat que le printf
précédent soit :
~/work/C/essais/strcat_test%> ./strcat_test
str3: Hello World
str3: Hello World

???
--
une bévue

Avatar
johann.d
"Une bévue" a écrit dans le message de
news:1hlaxg1.lsc8tbnkdf4N%

alors là, ce que je ne pige pas c'est qu'après "free(str3);" le
"printf("str3: %sn", str3);" donne le m^me résultat que le printf
précédent soit :
~/work/C/essais/strcat_test%> ./strcat_test
str3: Hello World
str3: Hello World


C'est parce que le garbagge collector n'est pas encore passé...

--
Johann.D

Avatar
pere.noel
johann.d wrote:

C'est parce que le garbagge collector n'est pas encore passé...


ça n'existe pas en C non ???

--
une bévue

Avatar
johann.d
"Une bévue" a écrit dans le message de
news:1hlb032.r8khcm1mrgvx0N%
johann.d wrote:

C'est parce que le garbagge collector n'est pas encore passé...


ça n'existe pas en C non ???


Bien dit.

C'est "simplement" que tu d'attends à ce que free fasse quelque chose, alors
qu'en pratique il ne fait quasiment rien...
Le malloc te réserve un bout de mémoire et t'en donne l'adresse.
Le free annule la réservation du bout de mémoire. Dans l'immense majorité
des cas il ne va rien se passer d'autre, surtout si tu ne fais pas d'autre
allocation par la suite.

Moralité, après le free tu effectues un accès à une zone mémoire qui ne
t'appartient plus, cela n'implique pas pour autant que la zone mémoire aura
été modifiée entre temps. En tout cas c'est un comportement indéfini (par
contre, arrêtez moi si je me trompe, il y a des machines ou des cas où le
gestionnaire de mémoire pourrait lever une exception ?).

Une bonne habitude est de toujours suivre un free d'une affectation à NULL :

ptr = malloc(...);
if (ptr == NULL) return AIEAIEAIE;
/* do some job */
free(ptr);
ptr = NULL;
/* do some other job */
printf("%sn", ptr); // ici ptr est NULL donc l'erreur devrait être franche

--
Johann.D


1 2 3 4 5