valeur d'un pointeur dans une fonction

Le
Kevin Denis
Bonjour,

(système linux)
On m'a fourni un fichier .so a utiliser dans mon code.
J'ai le code C de cette librairie, dont voici un extrait:
void u_min(int a, int b, valeur *result) {
result->value.i = (a < b) ? a : b;
}
Et du ulib.h associé:
typedef struct valeur {
struct {
int i;
char *p;
} value;
size_t size;
int (*expand)(struct valeur *);
} valeur;

Une fonction très simple, et la structure valeur associée.

Je peux résumer le code qui ne fonctionne pas à un programme simple:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "ulib.h"
int main(int argc, char*argv[]){
valeur v;
int a,b;
a=atoi(argv[1]); b=atoi(argv[2]);

printf("Valeur de value.i: %d",v.value.i);
u_min(a,b,&valor);
printf("essai de u_min %d",v.value.i);
return 0;
}

Le résultat attendu est le suivant:
le premier printf doit m'afficher une valeur quelconque (uninitialized),
le second doit me donner le minimum des deux chiffres donnés en paramètre.

Si j'utilise la bibliothèque .so fournie, alors les deux valeurs
v.value.i sont identiques (à la valeur uninitialized). Si je recompile
moi même la fonction (j'ai le .c après tout), alors le code ci-dessus
fonctionne. Pourquoi?

--
Kevin
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 2
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Olivier Miakinen
Le #23316271
Bonjour,

Le 28/04/2011 11:38, Kevin Denis a écrit :

(système linux)
On m'a fourni un fichier .so a utiliser dans mon code.
[...]
int main(int argc, char*argv[]){
valeur v;
int a,b;
a=atoi(argv[1]); b=atoi(argv[2]);

printf("Valeur de value.i: %drn",v.value.i);
u_min(a,b,&valor);



Je suppose que c'est bien v ici et pas valor.

printf("essai de u_min %drn",v.value.i);
return 0;
}

Le résultat attendu est le suivant:
le premier printf doit m'afficher une valeur quelconque (uninitialized),
le second doit me donner le minimum des deux chiffres donnés en paramètre.

Si j'utilise la bibliothèque .so fournie, alors les deux valeurs
v.value.i sont identiques (à la valeur uninitialized).



Si tu rajoutes une initialisation, par exemple v.valeur.i = 7, avant
l'appel de la fonction, c'est bien cette valeur qui s'affiche après ?

Si je recompile
moi même la fonction (j'ai le .c après tout), alors le code ci-dessus
fonctionne. Pourquoi?



Peut-être le .so a-t-il été compilé avec une certaine option
d'alignement et ton programme avec une autre ?
Kevin Denis
Le #23316301
Le 28-04-2011, Olivier Miakinen
(système linux)
On m'a fourni un fichier .so a utiliser dans mon code.
[...]
int main(int argc, char*argv[]){
valeur v;
int a,b;
a=atoi(argv[1]); b=atoi(argv[2]);

printf("Valeur de value.i: %drn",v.value.i);
u_min(a,b,&valor);



Je suppose que c'est bien v ici et pas valor.



oui.

printf("essai de u_min %drn",v.value.i);
return 0;
}

Le résultat attendu est le suivant:
le premier printf doit m'afficher une valeur quelconque (uninitialized),
le second doit me donner le minimum des deux chiffres donnés en paramètre.

Si j'utilise la bibliothèque .so fournie, alors les deux valeurs
v.value.i sont identiques (à la valeur uninitialized).



Si tu rajoutes une initialisation, par exemple v.valeur.i = 7, avant
l'appel de la fonction, c'est bien cette valeur qui s'affiche après ?



Effectivement. i ne semble jamais mis à jour.
Si je lui donne une valeur, cette valeur est conservée malgré
l'appel à la fonction.

Le .so fonctionne puisque j'ai d'auitres programmes qui l'utilisent et
qui marchent bien, pour info.

Si je recompile
moi même la fonction (j'ai le .c après tout), alors le code ci-dessus
fonctionne. Pourquoi?



Peut-être le .so a-t-il été compilé avec une certaine option
d'alignement et ton programme avec une autre ?



Plus d'infos la dessus?

Je compile très basiquement:
gcc -Wall -I. -L. -o hello hello.c -lulib
--
Kevin
Pascal J. Bourguignon
Le #23316291
Kevin Denis
Bonjour,

(système linux)
On m'a fourni un fichier .so a utiliser dans mon code.
J'ai le code C de cette librairie, dont voici un extrait:
void u_min(int a, int b, valeur *result) {
result->value.i = (a < b) ? a : b;
}
Et du ulib.h associé:
typedef struct valeur {
struct {
int i;
char *p;
} value;
size_t size;
int (*expand)(struct valeur *);
} valeur;

Une fonction très simple, et la structure valeur associée.

Je peux résumer le code qui ne fonctionne pas à un programme simple:
#include #include #include #include "ulib.h"
int main(int argc, char*argv[]){
valeur v;
int a,b;
a=atoi(argv[1]); b=atoi(argv[2]);

printf("Valeur de value.i: %drn",v.value.i);
u_min(a,b,&valor);
printf("essai de u_min %drn",v.value.i);
return 0;
}

Le résultat attendu est le suivant:
le premier printf doit m'afficher une valeur quelconque (uninitialized),
le second doit me donner le minimum des deux chiffres donnés en paramètre.

Si j'utilise la bibliothèque .so fournie, alors les deux valeurs
v.value.i sont identiques (à la valeur uninitialized). Si je recompile
moi même la fonction (j'ai le .c après tout), alors le code ci-dessus
fonctionne. Pourquoi?



Tu nous ment!
Le main présenté ci-dessus avec l'ulib.h donné, ne peut pas compiler.

S'il pouvait compiler:

1- le premier printf pourrait produire n'importe quoi. Par exemple,
faire sortir des dragons de ton nez, ou faire crasher le programme,
et pas seulement afficher une valeur quelconque.

2- même si ce premier printf continuait normalement, il n'y a absolument
aucune raison pour que u_min modifie v, tel que l'appel à u_min est
écrit.



--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
Kevin Denis
Le #23316351
Le 28-04-2011, Pascal J. Bourguignon
Tu nous ment!
Le main présenté ci-dessus avec l'ulib.h donné, ne peut pas compiler.



"un extrait de l'ulib.h". Par contre mon code est complet.

S'il pouvait compiler:

1- le premier printf pourrait produire n'importe quoi. Par exemple,
faire sortir des dragons de ton nez, ou faire crasher le programme,
et pas seulement afficher une valeur quelconque.



ou poster sur les news?

2- même si ce premier printf continuait normalement, il n'y a absolument
aucune raison pour que u_min modifie v, tel que l'appel à u_min est
écrit.



une explication?
--
Kevin
Pascal J. Bourguignon
Le #23316401
Kevin Denis
Peut-être le .so a-t-il été compilé avec une certaine option
d'alignement et ton programme avec une autre ?



Plus d'infos la dessus?



Compile la bibliothèque toi-même!



En supposant qu'on enlève tout les mensonges, ça marche parfaitement:

[ :0 tmp]$ cat-sources Makefile ulib.[hc] ulibclient.c
---- Makefile ----------------------------------------------------------
all:test
ulib.so.1.0.0: ulib.c
gcc -g -Wall -fPIC -I. -c -o ulib.o ulib.c
gcc -g -Wall -shared -Wl,-soname,libulib.so.1 -o libulib.so.1.0.0 ulib.o
libulib.so:libulib.so.1.0.0
ln -sf libulib.so.1.0.0 libulib.so.1
ln -sf libulib.so.1 libulib.so
ulibclient:ulibclient.c libulib.so.1
gcc -g -Wall -I. -o ulibclient ulibclient.c -L. -lulib
test:ulibclient
LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH ./ulibclient

---- ulib.c ------------------------------------------------------------
#include void u_min(int a, int b, valeur *result) {
result->value.i = (a < b) ? a : b;
}
---- ulib.h ------------------------------------------------------------
#include
typedef struct valeur {
struct {
int i;
char *p;
} value;
size_t size;
int (*expand)(struct valeur *);
} valeur;

extern void u_min(int a, int b, valeur *result);
---- ulibclient.c ------------------------------------------------------
#include #include #include #include "ulib.h"
int main(int argc, char*argv[]){
valeur v;
int a,b;
a2; bU5;
v.value.iB;
printf("Valeur de value.i: %drn",v.value.i);
u_min(a,b,&v);
printf("essai de u_min %drn",v.value.i);
return 0;
}
------------------------------------------------------------------------
[ :0 tmp]$ make test
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./ulibclient
Valeur de value.i: 42
essai de u_min 102
[ :0 tmp]$


--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
Pascal J. Bourguignon
Le #23316391
Kevin Denis
Le 28-04-2011, Pascal J. Bourguignon
Tu nous ment!
Le main présenté ci-dessus avec l'ulib.h donné, ne peut pas compiler.



"un extrait de l'ulib.h". Par contre mon code est complet.

S'il pouvait compiler:

1- le premier printf pourrait produire n'importe quoi. Par exemple,
faire sortir des dragons de ton nez, ou faire crasher le programme,
et pas seulement afficher une valeur quelconque.



ou poster sur les news?



Oui, c'est possible.


2- même si ce premier printf continuait normalement, il n'y a absolument
aucune raison pour que u_min modifie v, tel que l'appel à u_min est
écrit.



une explication?



l'appel à u_min était écrit avec valor au lieu de v.

--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
Olivier Miakinen
Le #23316381
Le 28/04/2011 12:38, Kevin Denis a écrit :

Si tu rajoutes une initialisation, par exemple v.valeur.i = 7, avant
l'appel de la fonction, c'est bien cette valeur qui s'affiche après ?



Effectivement. i ne semble jamais mis à jour.
Si je lui donne une valeur, cette valeur est conservée malgré
l'appel à la fonction.



Ok.

Le .so fonctionne puisque j'ai d'autres programmes qui l'utilisent et
qui marchent bien, pour info.



C'est une info importante.

Peut-être le .so a-t-il été compilé avec une certaine option
d'alignement et ton programme avec une autre ?



Plus d'infos la dessus?



On trouve quelques infos en cherchant par exemple ici :

Tu peux éventuellement essayer un truc de ce genre, avec le .so comme
avec le résultat de ta propre compilation, pour voir si le résultat de
u_min est mis à un endroit différent entre les deux tests (attention,
code non testé, je te laisse corriger d'éventuels bugs d'inattention).

===================================== void ptab(char *t, int len)
{
int idx;
printf("Valeurs :");
for (idx = 0; idx < len; idx++) {
printf(" %02x", t[idx]);
}
printf("n");
}

int main(int argc, char*argv[]){
static char v[32];
int a,b;
a=atoi(argv[1]); b=atoi(argv[2]);

ptab(v, 32);
u_min(a, b, (valeur *)v);
ptab(v, 32);
return 0;
}
======================================
Kevin Denis
Le #23316471
Le 28-04-2011, Pascal J. Bourguignon
Peut-être le .so a-t-il été compilé avec une certaine option
d'alignement et ton programme avec une autre ?



Plus d'infos la dessus?



Compile la bibliothèque toi-même!

En supposant qu'on enlève tout les mensonges, ça marche parfaitement:



On se calme, on boit frais, et on relit:
"Si je recompile moi même la fonction (j'ai le .c après tout), alors
le code ci-dessus fonctionne."

Pourquoi refaire ce qui marche?
--
Kevin
Antoine Leca
Le #23317501
Kevin Denis écrivit :
(système linux)



architecture ?
En particulier, sizeof(char*) par rapport à sizeof(int) ?
et combien de paramètres sont passés par des registres ?
ou une différence entre -kpic et -kPIC ?

Si j'utilise la bibliothèque .so fournie, alors les deux valeurs
v.value.i sont identiques (à la valeur uninitialized). Si je recompile
moi même la fonction (j'ai le .c après tout), alors le code ci-dessus
fonctionne. Pourquoi?



Peut-être parce que les versions récentes de GCC mettent en inline la
fonction u_min au sein du .so (donc la bibliothèque fonctionne bien en
interne) et que ce à quoi tu accèdes depuis l'extérieur est une version
ancienne ou obsolète ou que sais-je, avec une autre forme pour la
structure valeur ?

Sinon, tu peux aussi essayer de fabriquer ton propre .so avec cette
seule fonction, et comparer les résultats (qui doivent être identiques
pour du code PIC).


Antoine
Antoine Leca
Le #23317491
Kevin Denis écrivit :
On se calme, on boit frais, et on relit:
"Si je recompile moi même la fonction (j'ai le .c après tout), alors
le code ci-dessus fonctionne."

Pourquoi refaire ce qui marche?



Si j'ai bien lu l'enfilade, le .so ne marche pas, lui.


Antoine
Publicité
Poster une réponse
Anonyme