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

valeur d'un pointeur dans une fonction

11 réponses
Avatar
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\r\n",v.value.i);
u_min(a,b,&valor);
printf("essai de u_min %d\r\n",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

10 réponses

1 2
Avatar
Olivier Miakinen
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 ?
Avatar
Kevin Denis
Le 28-04-2011, Olivier Miakinen <om+ 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.



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
Avatar
Pascal J. Bourguignon
Kevin Denis writes:

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: %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 {}.
Avatar
Kevin Denis
Le 28-04-2011, Pascal J. Bourguignon a écrit :
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
Avatar
Pascal J. Bourguignon
Kevin Denis writes:

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 <ulib.h>
void u_min(int a, int b, valeur *result) {
result->value.i = (a < b) ? a : b;
}
---- ulib.h ------------------------------------------------------------
#include <sys/types.h>

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 <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#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 {}.
Avatar
Pascal J. Bourguignon
Kevin Denis writes:

Le 28-04-2011, Pascal J. Bourguignon a écrit :
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 {}.
Avatar
Olivier Miakinen
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 :
<http://www.google.fr/search?q=%23pragma+align>

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;
}
======================================
Avatar
Kevin Denis
Le 28-04-2011, Pascal J. Bourguignon a écrit :
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
Avatar
Antoine Leca
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
Avatar
Antoine Leca
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
1 2