InCoMpReHeNsIbLe (pointeur non portable !?!*#...)

InCoMpReHeNsIbLe (pointeur non portable !?!*#...) - C - Programmation

Marsh Posté le 21-07-2006 à 09:53:44    

Salut à tous !
 
Alors là je dois dire que c'est trés trés fort ... J'ai un programme qui fonctionne trés bien sur la machine ou je l'ai implémenté, mais qui n'était pas du tout portable à cause de son interface graphique GTK (enfin il à juste fallu que j'insere le runtime windows dans l'install). Soit. Mais alors une fois GTK installé sur la machine recevante, l'erreur la plus improbable de tous les temps est arrivée (il a deja fallu lutter pour voir d'ou ca venait tellemment c'était imprévisible 8O )
 Je m'explique : Au debut de mon programme, je fais une saisie de 'selection gtk' (selection du chemin du fichier à exploiter). Et je stock ce chemin dans un gchar* chemin, qui est mis dans ma structure principale (en GTK pour ceux qui ne connaissent pas, on met tous les elements à passer dans les fonctions dans une même structure car les fonctions callbacks ne supportent qu'un argument). Enfin bref tout ca me paraissait parfait. SAUF QUE sur la machine recevante, le chemin est erroné (il devait me filer l'adresse du pointeur un truc du genre enfin c'était illisible) et alors LA je dois dire que ca m'a vraiment stupefai ! Sincerement je ne comprends pas POURQUOI ca fait ca c'est hallucinant !  
 Si quelqu'un à la moindre idée, qu'il reponde parce que en plsu ca intervient alors que je dois rendre le tout donc ca la fout vraiment mal !!!
 
Merci, Skip

Reply

Marsh Posté le 21-07-2006 à 09:53:44   

Reply

Marsh Posté le 21-07-2006 à 10:09:46    

C'est parce qu'il manque un point-virgule à la ligne 42.

Reply

Marsh Posté le 21-07-2006 à 10:20:07    

Non mais t'es pas drole la mdr
Je suis vraiment dans la merde moi ! Un logiciel non portable c'est pas trés interessant quoi :/

Reply

Marsh Posté le 21-07-2006 à 11:37:31    

Et tu crois vraiment qu'on peut t'aider avec ce que tu racontes, là? [:moule_bite]


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 21-07-2006 à 11:57:04    

skeye a écrit :

Et tu crois vraiment qu'on peut t'aider avec ce que tu racontes, là? [:moule_bite]


 
 Et bien oui ... Peut être que le même problème est arrivé à quelqu'un ?
On me dit sur un autre forum que c'est relativement courant. J'attends donc des reponses ;)

Reply

Marsh Posté le 21-07-2006 à 11:59:31    

euh...non.
Sans aucune ligne de code à part sortir la boule de crystal on peut pas faire grand chose, hein...[:dawao]


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 21-07-2006 à 12:02:50    

skeye a écrit :

euh...non.
Sans aucune ligne de code à part sortir la boule de crystal on peut pas faire grand chose, hein... [:dawao]

 


mais si !
mais moi au lieu de taper gtk, c'est DTC , et ca marchait pas ...
au final j'ai abandonné..
 
vous faites pas d'efforts le vendredi

Reply

Marsh Posté le 21-07-2006 à 12:07:34    

http://utp.blogspirit.com/images/medium_manuelutilisationboulecristal.jpg

Reply

Marsh Posté le 21-07-2006 à 12:10:00    

skeye a écrit :

euh...non.
Sans aucune ligne de code à part sortir la boule de crystal on peut pas faire grand chose, hein...[:dawao]


 Bah disons que le code je peut te le sortir mais le problème est plus profond je pense ... Enfin voici toujour les bouts de codes qui nous interesse :

Code :
  1. typedef struct app
  2. {
  3.     (...)
  4.     gchar* chemin;
  5. }APP;
  6. typedef struct dede
  7. {
  8.     (...)
  9.     gchar* chemin;
  10. }DEDE;
  11. void recuperer_chemin (GtkWidget *bouton, GtkWidget *file_selection)
  12. {
  13.     (...)
  14.     const gchar* prefixe = NULL;
  15.     const gchar* chemin = NULL;
  16.     chemin = gtk_file_selection_get_filename(GTK_FILE_SELECTION (file_selection) );
  17.     gtk_widget_destroy(file_selection);
  18.     (...)
  19.             prefixe = gtk_entry_get_text(GTK_ENTRY(pEntry));
  20.             break;
  21.     (...)
  22.     if(prefixe){
  23.         strcat((gchar*)chemin,"/" );
  24.         strcat((gchar*)chemin,prefixe);
  25.         APP *app = creer_interface(chemin);
  26.         gtk_widget_show_all(app->window);
  27.     }
  28.     else{
  29.         (...)
  30.     }
  31. }
  32. APP* creer_interface(const gchar* chemin)
  33. {
  34.     (...)
  35.     APP *app = NULL;
  36.    
  37.     if((app = (APP*)malloc(sizeof(APP))) != NULL)
  38.     { 
  39.         (...)
  40.         app->chemin = (char*)chemin;
  41.        
  42.         (...)
  43.             /* Creation du boutton 'afficher' (insere dans la table) */
  44.             app->button = gtk_button_new_with_label ("Thanks to choose an area" );
  45.             g_signal_connect (G_OBJECT (app->button), "clicked", G_CALLBACK (AffichRep), app);
  46.             gtk_table_attach_defaults(GTK_TABLE(app->table), app->button, 6, 11, 2, 7);
  47.            
  48.         (...)
  49.     }
  50.    
  51.     return app;
  52. }
  53. void AffichRep (GtkWidget *bouton, APP* app)
  54. {
  55.   (...)
  56.   DEDE *dede;
  57.   (...)
  58.  
  59.   if(app->affich){
  60.      
  61.       dede = (DEDE*)malloc(sizeof(DEDE));           
  62.      
  63.       (...)
  64.           dede->chemin = app->chemin;
  65.          
  66.           /* Création de l'image affichée (insérée dans la vbox2) */
  67.           for(k=0;k<256;k++)nom[k]=(int)NULL;
  68.           for(k=0;k<4;k++)num[k]=(int)NULL;
  69.           strcpy(nom,app->chemin);
  70.           sprintf(num,"%d",dede->etat);
  71.           strcat(nom,num);
  72.           strcat(nom,".bmp" );
  73.           dede->pImg2 = gtk_image_new_from_file (nom);
  74.           gtk_box_pack_start (GTK_BOX (pVbox2), dede->pImg2, TRUE, TRUE, 0);
  75.           (...)
  76.       // Voila pourquoi j'utilises dede :
  77.               g_signal_connect(G_OBJECT(pSuiv), "clicked", G_CALLBACK(OnClickNext), dede);
  78.   (...)
  79.   gtk_widget_show_all (pWindow);
  80. }

Reply

Marsh Posté le 21-07-2006 à 13:24:54    

Code :
  1. const gchar* chemin = NULL;   
  2. chemin = gtk_file_selection_get_filename(GTK_FILE_SELECTION (file_selection) );


 
A mon avis va falloir que tu regardes la premiere ligne

Reply

Marsh Posté le 21-07-2006 à 13:24:54   

Reply

Marsh Posté le 21-07-2006 à 14:21:33    

caddie a écrit :

Code :
  1. const gchar* chemin = NULL;   
  2. chemin = gtk_file_selection_get_filename(GTK_FILE_SELECTION (file_selection) );


 
A mon avis va falloir que tu regardes la premiere ligne


 
 Euh ??? Merci d'être un peu plus explicite car il n'y à aucune erreur de code là  :??:

Reply

Marsh Posté le 21-07-2006 à 14:22:55    

ça fait des années que j'ai pas fait de C...m'enfin const initialisé à NULL puis modifié ça me parait louche aussi...[:jagstang]


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 21-07-2006 à 14:31:28    

skip78 a écrit :

Euh ??? Merci d'être un peu plus explicite car il n'y à aucune erreur de code là  :??:


[:fenston]

Reply

Marsh Posté le 21-07-2006 à 14:42:48    

skip78 a écrit :

Euh ??? Merci d'être un peu plus explicite car il n'y à aucune erreur de code là  :??:


 
Bon, en tout cas félicitation pour ta superbe structure DEDE, gage d'un code de Qualité.  
DEDE c'est un peu trop commun. tu devrais plutot la renommer en TOTO ou TATA

Reply

Marsh Posté le 21-07-2006 à 23:22:23    

la zone memoire sur laquelle pointe 'chemin' .... qui c'est qui l'alloue d'une part, et quelle est sa taille d'autre part ?

Reply

Marsh Posté le 21-07-2006 à 23:46:09    

Code :
  1. APP* creer_interface(const gchar* chemin)
  2. {
  3.    (...)
  4.    APP *app = NULL;
  5.    if((app = (APP*)malloc(sizeof(APP))) != NULL)
  6.    { 
  7.        (...)
  8.        app->chemin = g_strdup(chemin); // à libérer plus tard
  9.        (...)
  10. }

Reply

Marsh Posté le 22-07-2006 à 00:15:01    

skeye a écrit :

ça fait des années que j'ai pas fait de C...m'enfin const initialisé à NULL puis modifié ça me parait louche aussi...[:jagstang]


non, chemin est un pointeur sur un gchar constant ! il peut modifier le pointeur, mais pas la chaine sur laquelle pointe ledit gchar.
de plus, à partir du moment ou la propriété de constance est conservée ou augmentée, alors tu peux parfaitement faire un truc du genre :

Code :
  1. char *prout = NULL;
  2. const char *caca = NULL;
  3. prout = "kikoo lol";
  4. caca = "asv lol ?";
  5. prout[2] = 'o'; // ok j'ai le droit
  6. caca = prout; // la constance de prout est augmentée : je ne peux plus modifier la chaine "kikoo lol";
  7. caca[2] = 'o'; // BOUM


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 22-07-2006 à 08:38:02    

Harkonnen a écrit :

non, chemin est un pointeur sur un gchar constant ! il peut modifier le pointeur, mais pas la chaine sur laquelle pointe ledit gchar.
de plus, à partir du moment ou la propriété de constance est conservée ou augmentée, alors tu peux parfaitement faire un truc du genre :

Code :
  1. char *prout = NULL;
  2. const char *caca = NULL;
  3. prout = "kikoo lol";
  4. caca = "asv lol ?";
  5. prout[2] = 'o'; // ok j'ai le droit
  6. caca = prout; // la constance de prout est augmentée : je ne peux plus modifier la chaine "kikoo lol";
  7. caca[2] = 'o'; // BOUM



 
Bon ok, heureusement que ça fait longtemps que j'ai pas touché à du C, quoi...[:petrus75]


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 22-07-2006 à 09:07:38    


 
Non je voulais dire dans la fonction recuperer_chemin. Parce que les strcat semblent douteux.

Reply

Marsh Posté le 23-07-2006 à 21:57:50    

Voilà ce qui est dit dans la doc GTK sur la fonction gtk_file_selection_get_filename

Citation :

This function returns the selected filename in the GLib file name encoding. To convert to UTF-8, call g_filename_to_utf8(). The returned string points to a statically allocated buffer and should be copied if you plan to keep it around.

Quand tu fais ensuite un  gtk_widget_destroy(file_selection); ton chemin doit pointer sur une zone mémoire non valide.
De toute façon, il est bien indiqué que tu dois recopier le chemin si tu veux le conserver et le manipuler, enfin je suppose car l'anglais et moi... :pt1cable:


Message édité par Trap D le 23-07-2006 à 22:02:37
Reply

Marsh Posté le 29-08-2006 à 11:11:47    

En effet on m'à souligné le même point sur un autre forum et j'ai essayé en vain de copier mon chemin sur une chaine de caractere dynamique.
Cela étant dit je vais essayer de repenser le truc avec cette indication on va bien voir ce que ca donne :)
 
 En tout cas je suis toujours dans la même merde ...  :pfff:  
 
P.S. Caddie pourquoi tant de haine ?  :wahoo:  :hello:

Reply

Marsh Posté le 29-08-2006 à 11:18:58    

skip78 a écrit :


P.S. Caddie pourquoi tant de haine ?  :wahoo:  :hello:


 
Non aucune haine ! juste un moment d'égarement sans intêret.  
De plus ma contribution ayant été complétement fausse je préfére m'écraser

Reply

Marsh Posté le 29-08-2006 à 12:02:06    

ok pas de problèmes.
 
Bon sinon mon programme marche sur certaines machines, que je fasse une copie de mon chemin en dynamique ou pas. J'en conclus donc que c'est un problème de depassement de memoire :( si quelqu'un se sent de m'expliquer comment on se sert de valgrind (deja comment l'installer mdr)

Reply

Marsh Posté le 29-08-2006 à 15:43:17    

mué bon apparement Valgrind c'est sous Linux uniquement :/


Message édité par skip78 le 29-08-2006 à 15:43:59
Reply

Marsh Posté le 29-08-2006 à 16:08:38    

Harkonnen a écrit :

non, chemin est un pointeur sur un gchar constant ! il peut modifier le pointeur, mais pas la chaine sur laquelle pointe ledit gchar.
de plus, à partir du moment ou la propriété de constance est conservée ou augmentée, alors tu peux parfaitement faire un truc du genre :

Code :
  1. char *prout = NULL;
  2. const char *caca = NULL;
  3. prout = "kikoo lol";
  4. caca = "asv lol ?";
  5. prout[2] = 'o'; // ok j'ai le droit
  6. caca = prout; // la constance de prout est augmentée : je ne peux plus modifier la chaine "kikoo lol";
  7. caca[2] = 'o'; // BOUM



 
je vois pas pourquoi la constance de prout changerai :??:
ce qui fait le boum c'est que l'écriture via caca pue du cul pour le compilo.
 
de toutes manières son problème c'est qu'il a tellement de trous dans le zizi, qu'il arrose partout quand il va aux toilettes.

Reply

Marsh Posté le 29-08-2006 à 16:17:22    

bjone a écrit :

je vois pas pourquoi la constance de prout changerai :??:
ce qui fait le boum c'est que l'écriture via caca pue du cul pour le compilo.


 
ben elle change pas, ce qui change c'est que la chaine (et pas le pointeur) passe du statut modifiable à non modifiable.
 
si mes souvenirs sont exacts, je peux écrire caca=prout, mais pas prout=caca (car la constance de la chaine pointée est augmentée)


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 29-08-2006 à 16:28:07    

moi je ferais déjà un truc genre:
 

Code :
  1. char Path[FILE_MAX_PATH+1]; /* chépu y'a une constante qui va bien */
  2. gchar *chemin;
  3. chemin = gtk_file_selection_get_filename(GTK_FILE_SELECTION (file_selection) );
  4. if( !chemin )
  5.    return PROUT_CODE;
  6. memset( Path, 0, sizeof(Path) );
  7. strncpy( Path, chemin, sizeof(Path)-1 );
  8. gtk_widget_destroy(file_selection);


 
en fait c'est relou les char * :D

Reply

Marsh Posté le 29-08-2006 à 16:29:23    

Harkonnen a écrit :

ben elle change pas, ce qui change c'est que la chaine (et pas le pointeur) passe du statut modifiable à non modifiable.
 
si mes souvenirs sont exacts, je peux écrire caca=prout, mais pas prout=caca (car la constance de la chaine pointée est augmentée)


 
ok on se comprends  :whistle:

Reply

Marsh Posté le 29-08-2006 à 16:29:52    

c'est le C qui est relou :o


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 29-08-2006 à 16:35:16    

c'est vrai que pour tout ce qui est administratif c'est daubique.
 
mais une fois que tu as accès a un framebuffer de carte vidéo ça deviens plus drôle tout de suite  :D

Reply

Marsh Posté le 30-08-2006 à 14:43:57    

skip78 a écrit :

Code :
  1. chemin = gtk_file_selection_get_filename(GTK_FILE_SELECTION (file_selection) );



Je ne sais pas comment fonctionne gtk_file_selection_get_filename mais il n'y a que 2 possibilités
1) cette fonction alloue de la mémoire, la remplit avec ton chemin et te renvoie un pointeur sur la zone allouée et t'as rien à faire qu'à penser à la libérer plus tard
2) cette fonction remplit une zone statique avec ton chemin et te renvoie un pointeur sur cette zone (comme le fait "getenv() par exemple). Là, t'es sèrieusement embêté parce que 2 appels successifs à ta fonction écrasent l'ancienne valeur par la nouvelle (la zone statique étant la même). Donc t'es obligé, après chaque appel, de recopier les infos dans une variable à toi déjà allouée comme il faut (et là, la solution de Bjone est parfaite)
 

bjone a écrit :

moi je ferais déjà un truc genre:
 

Code :
  1. char Path[FILE_MAX_PATH+1]; /* chépu y'a une constante qui va bien */
  2. gchar *chemin;
  3. chemin = gtk_file_selection_get_filename(GTK_FILE_SELECTION (file_selection) );
  4. if( !chemin )
  5.    return PROUT_CODE;
  6. memset( Path, 0, sizeof(Path) );
  7. strncpy( Path, chemin, sizeof(Path)-1 );
  8. gtk_widget_destroy(file_selection);




Dommage de faire un memset écrasé par le strncpy car si la limite de "n" octets n'est pas atteinte, strncpy rajoute le 0 final.
Dommage aussi de ne pas réutiliser la macro du départ (mais ça, ça dépend des préférences de chacun)...

Code :
  1. Path[FILE_MAX_PATH]=0;
  2. strncpy( Path, chemin, FILE_MAX_PATH);

Message cité 1 fois
Message édité par Sve@r le 30-08-2006 à 14:59:47

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 30-08-2006 à 15:27:58    

bin ouais mais si la limite est atteinte, le 0 final n'est pas rajouté.

Reply

Marsh Posté le 30-08-2006 à 15:30:39    

et effetivement pour la macro, je préfère ne pas la réutiliser, car si je veux changer la taille du tampon en minimisant l'intrusion dans le code, je n'ai juste qu'a changer la déclaration de Path et tout le reste évolue en fonction de.

Reply

Marsh Posté le 30-08-2006 à 20:47:50    

bjone a écrit :

bin ouais mais si la limite est atteinte, le 0 final n'est pas rajouté.


Oui mais si ça arrive, le 0 ne sera nécessaire qu'au dernier octet d'où le "Path[FILE_MAX_PATH]=0;" ou "Path[sizeof(Path) - 1]=0;"...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 01-09-2006 à 11:59:07    

Sve@r a écrit :

Je ne sais pas comment fonctionne gtk_file_selection_get_filename mais il n'y a que 2 possibilités
1) cette fonction alloue de la mémoire, la remplit avec ton chemin et te renvoie un pointeur sur la zone allouée et t'as rien à faire qu'à penser à la libérer plus tard
2) cette fonction remplit une zone statique avec ton chemin et te renvoie un pointeur sur cette zone (comme le fait "getenv() par exemple). Là, t'es sèrieusement embêté parce que 2 appels successifs à ta fonction écrasent l'ancienne valeur par la nouvelle (la zone statique étant la même).
Donc t'es obligé, après chaque appel, de recopier les infos dans une variable à toi déjà allouée comme il faut (et là, la solution de Bjone est parfaite)


 Bah à vrai dire je n'apelle cette fonction qu'au départ pour avoir le chemin des fichiers à exploiter ; je ne laisse pas à l'utilisateur la possibilité de changer le chemin aprés coup car le traitement d'image peut durer plusieurs heures. Enfin bref je ne vais pas rentrer dans les details ...
 
 Toujours est il que ce problème ne devrait donc pas se poser. Maintenant il faut preciser que le programme fonctionne sur certaines machines mais présente le bug lorsque je suis sur certaines machines (plus petites à mon avis) donc il s'agirai bien d'un depassement memoire, et changer les char* en path je pense pas que ca change grand chose étant donné que le prog fonctionne trés bien à la base ;)

Message cité 1 fois
Message édité par skip78 le 01-09-2006 à 11:59:50
Reply

Marsh Posté le 01-09-2006 à 13:56:44    

skip78 a écrit :

Toujours est il que ce problème ne devrait donc pas se poser.


Tout dépend du fonctionnement interne de cette fonction (voir la doc)
 

skip78 a écrit :

étant donné que le prog fonctionne trés bien à la base ;)


Il arrive très souvent qu'un défaut de programmation reste invisible parce que "le programme fonctionne bien". Puis on rajoute un truc totalement insignifiant, style 'printf("coucou" )' et là, plus rien ne va plus. C'est la notion de "comportement indéfini"
 
Ex :


int main()
{
    char string[1]="Hello";
    printf("%s\n", string);
}


Il est probable que cet exemple véreux fonctionnera dans 99% des cas parce que la zone mémoire située derrière "string" n'est pas utilisée. Mais si on rajoute un "int i" avant ou après string, on risque d'avoir des pb...


Message édité par Sve@r le 01-09-2006 à 17:46:40

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 06-09-2006 à 09:52:28    

Iop. Mon problème principal, à savoir le pointeur non portable, je l'ai résolu en copiant chaque const char* dans un gchar, caractere par caractere, et en ajoutant le \0 à la fin (sans quoi ca marchait pas ...)
 
 Quant aux deux autres problèmes, à savoir que lors de la première utilisation du programme sur une machine le graph n'est pas forcement bon, et que souvent il ya un stop lors du passage entre allegro et gtk, je n'ai 'resolu' que le second, en affichant la console pour faire le lien ...
 
 J'éspère que le problème d'affichage ne se reproduira plus. En tout cas il est vraiment etonnant :/
 
 En fait il affiche les points 2 fois plus haut que prevu dans le repere c'est pathetique.

Reply

Marsh Posté le 06-09-2006 à 17:03:02    

skip78 a écrit :

En fait il affiche les points 2 fois plus haut que prevu dans le repere c'est pathetique.


Ben t'as qu'à diviser toutes tes ordonnées par 2...  :pt1cable:


Message édité par Sve@r le 06-09-2006 à 17:06:27

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 07-09-2006 à 09:48:57    

lol non je peux pas puisque c'est uniquement lors de la première utilisation :/

Reply

Marsh Posté le 07-09-2006 à 12:46:08    

Bonjour
Je pratique le GTK de temps à autre sur linux et j'ai pu constater que les valeurs stockées dans les widgets ne sont pas persistantes et donc disparaissent dès que l'on fait un gtk_widget_destroy y compris les widgets inclus.
Dans le cas présent, il est impératif de copier le contenu de la chaine dans  une zone mémoire qui sera persistante au moins jusqu'à son utilisation finale avant de faire le gtk_widget_destroy
Si cela plante sur certains systèmes et par sur d'autres, c'est que les dit systèmes ne gèrent pas le tas de la même façon et de plus la gestion des dit tas dépend de la mémoire vive disponible et utilisée et de la quantité à allouer; bref il est pratiquement impossible de prévoir cette gestion.
On peut donc dire que tu as de la chance quand ça ne plante pas et un comportement normal quand ça plante.
GTK gère convenablement sa mémoire (ce qui évite les fuites) et la rend disponible dès qu'il n'en a plus besoin (gtk_widget_destroy) et elle peut donc être immédiatement réutilisée.
La documentation GTK est pénible car uniquement en anglais, mais avant d'incriminer GTK, il faut la lire pour s'assurer de la bonne utilisation d'un widget.
Bon courage !

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed