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

adresse d'une variable d'environnement

23 réponses
Avatar
Kevin Denis
Bonjour,

je suis sur un système linux x86 32bits.
J'ai des variables d'environnements, et depuis un programme C, je
souhaite connaitre leurs adresses.
Typiquement:
MAVAR="blablable(...)blablbabla"
export MAVAR

Si je regarde le man, je vois que la fonction getenv à l'air de
faire l'affaire. getenv renvoie un pointeur, et il est de type:
#include <stdlib.h>
char *getenv (const char *name);

J'écris donc:

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

int main(void){
char *p = NULL; //je vais utiliser un pointeur
p = getenv('MAVAR'); //getenv me renvoie un pointeur
printf('Adresse de MAVAR: %p', p); //j'affiche le pointeur
return 0; //comme ça gcc râle moins
}

sauf que ça ne fonctionne pas
J'ai lors de la compilation des warning:
warning: multi-character character constant
et
warning: passing arg 1 of `getenv' makes pointer from integer without a cast

et au lancement le programme ne fait rien d'autre qu'un segfault.

Un conseil pour me montrer ce que je fais mal?
Merci
--
Kevin

10 réponses

1 2 3
Avatar
Xavier Roche
Le 22/08/2011 15:39, Kevin Denis a écrit :
p = getenv('MAVAR'); //getenv me renvoie un pointeur



p = getenv("MAVAR"); /* getenv me renvoie un pointeur */

Les '' sont réservés en C aux char ('a') [éventuellement aux versions
sur 2 ou 4 octets, mais c'est hors-sujet ici] et non aux chaînes.
Avatar
Éric Lévénez
Le 22/08/11 15:50, Xavier Roche a écrit :
Le 22/08/2011 15:39, Kevin Denis a écrit :
p = getenv('MAVAR'); //getenv me renvoie un pointeur



p = getenv("MAVAR"); /* getenv me renvoie un pointeur */

Les '' sont réservés en C aux char ('a') [éventuellement aux versions
sur 2 ou 4 octets, mais c'est hors-sujet ici] et non aux chaînes.



Et idem pour le printf, auquel en plus il manque en plus le n.

Mais sinon vouloir connaître l'adresse d'une variable d'environnement en
C, laisse supposer que pour toi (Kevin) cette variable est la même que
sous shell. Ceci n'est pas vrai. Chaque programme a son propre espace
mémoire virtuel, et les variables shell sont passées par valeur et non
par adresse.

--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/&gt;
Avatar
Xavier Roche
Le 22/08/2011 17:38, Éric Lévénez a écrit :
Mais sinon vouloir connaître l'adresse d'une variable d'environnement en
C, laisse supposer que pour toi (Kevin) cette variable est la même que
sous shell.



C'est du reste le même comportement que lorsque l'on exporte une
variable ("export") dans un script: une fois terminé le script,
l'appelant (en général le shell) ne "verra" pas cette modification qui
était interne au script.
Avatar
Pascal J. Bourguignon
Xavier Roche writes:

Le 22/08/2011 17:38, Éric Lévénez a écrit :
Mais sinon vouloir connaître l'adresse d'une variable d'environnement en
C, laisse supposer que pour toi (Kevin) cette variable est la même que
sous shell.



C'est du reste le même comportement que lorsque l'on exporte une
variable ("export") dans un script: une fois terminé le script,
l'appelant (en général le shell) ne "verra" pas cette modification qui
était interne au script.



C'est pire. Je ne me souviens pas avoir vu aucune garantie dans la
norme POSIX telle que: getenv("V")==(f(),getenv("V")).
Donc l'intérêt d'obtenir cette adresse est nul.

Le standard énonce explicitely:

The string pointed to may be overwritten by a subsequent call to
getenv(), [CX] [Option Start] setenv(), or unsetenv(), [Option End]
but shall not be overwritten by a call to any other function in
this volume of IEEE Std 1003.1-2001.


--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
Avatar
Xavier Roche
Le 22/08/2011 18:13, Pascal J. Bourguignon a écrit :
C'est pire. Je ne me souviens pas avoir vu aucune garantie dans la
norme POSIX telle que: getenv("V")==(f(),getenv("V")).



C'est du reste il me semble ce qui se passe sous Windows (bon, certes,
pas POSIX pour un sou, mais passons), où getenv() renvoi un tableau
calculé à partir de la "vrai" version (qui est notamment codée sur des
caractères 16-bit) en mode Unicode.
Avatar
espie
In article <j2u508$hhj$,
Xavier Roche wrote:
Le 22/08/2011 18:13, Pascal J. Bourguignon a écrit :
C'est pire. Je ne me souviens pas avoir vu aucune garantie dans la
norme POSIX telle que: getenv("V")==(f(),getenv("V")).



C'est du reste il me semble ce qui se passe sous Windows (bon, certes,
pas POSIX pour un sou, mais passons), où getenv() renvoi un tableau
calculé à partir de la "vrai" version (qui est notamment codée sur des
caractères 16-bit) en mode Unicode.



C'est pas plus specifique a Windows que ca.

En fait, getenv() fait partie de cette vieille famille de fonctions C
dont font aussi partie basename(), gethostbyname() et assimiles: tous
ces trucs renvoient des pointeurs sur des tampons internes a la libc
(ces derniers tres souvent statiques), et ces pointeurs ne sont guere
valides que jusqu'au prochain appel a la meme fonction. C'est plus ou
moins bien documente, et parfois buggue... par exemple, je suis deja
tombe sur une implementation qui utilisait le meme tampon pour dirname
et pour basename.

Bref, pour que ca fonctionne, ca reclame une implementation bien specifique,
et pas mal de ces fonctions ne sont pas trop thread-safe. Certaines ont
ete remplacees par des versions qui rendent explicites la gestion du tampon,
cf gethostbyname_r. Pour autant que je le sache, ce n'est pas le cas de
getenv().
Avatar
Kevin Denis
Le 22-08-2011, Éric Lévénez a écrit :
p = getenv('MAVAR'); //getenv me renvoie un pointeur



p = getenv("MAVAR"); /* getenv me renvoie un pointeur */

Les '' sont réservés en C aux char ('a') [éventuellement aux versions
sur 2 ou 4 octets, mais c'est hors-sujet ici] et non aux chaînes.



Et idem pour le printf, auquel en plus il manque en plus le n.

Mais sinon vouloir connaître l'adresse d'une variable d'environnement en
C, laisse supposer que pour toi (Kevin) cette variable est la même que
sous shell. Ceci n'est pas vrai. Chaque programme a son propre espace
mémoire virtuel, et les variables shell sont passées par valeur et non
par adresse.



Je souhaite faire une sorte de:
:~$ MAVAR="abcdefghijklm"
:~$ export MAVAR
:~$ ./monprog
l'adresse de MAVAR est à: 0xbfffff0c
--
Kevin
Avatar
Éric Lévénez
Le 22/08/11 20:17, Marc Espie a écrit :

Bref, pour que ca fonctionne, ca reclame une implementation bien specifique,
et pas mal de ces fonctions ne sont pas trop thread-safe. Certaines ont
ete remplacees par des versions qui rendent explicites la gestion du tampon,
cf gethostbyname_r. Pour autant que je le sache, ce n'est pas le cas de
getenv().



Une explication du manque de getenv_r est donnée ici ("static data") :

<http://pubs.opengroup.org/onlinepubs/009695399/functions/getenv.html&gt;

Les pointeurs retournés par getenv étaient (ou peut-être même "sont")
les mêmes que ceux se trouvant dans envp, le troisième argument à main.

--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/&gt;
Avatar
Éric Lévénez
Le 22/08/11 20:45, Kevin Denis a écrit :

Je souhaite faire une sorte de:
:~$ MAVAR="abcdefghijklm"
:~$ export MAVAR
:~$ ./monprog
l'adresse de MAVAR est à: 0xbfffff0c



Et pour toi, 0xbfffff0c, représenterait :
- Une adresse virtuelle dans ton shell ?
- Une adresse virtuelle dans monprog ?

--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/&gt;
Avatar
Kevin Denis
Le 22-08-2011, Éric Lévénez a écrit :
Je souhaite faire une sorte de:
:~$ MAVAR="abcdefghijklm"
:~$ export MAVAR
:~$ ./monprog
l'adresse de MAVAR est à: 0xbfffff0c



Et pour toi, 0xbfffff0c, représenterait :
- Une adresse virtuelle dans ton shell ?
- Une adresse virtuelle dans monprog ?



Dans monprog bien entendu.
Enfin, le bout de code C que je donnais m'avait
paru clair (?)
--
Kevin
1 2 3