Votre question

GetOpenFileName() problème

Tags :
  • Programme
  • Programmation
Dernière réponse : dans Programmation
28 Novembre 2008 17:13:20

Bonjour,

J'ai programmé une fonction qui ouvre un fichier avec la boite de dialogue d'ouverture de fichier à savoir la fonction GetOpenFileName.

Tout fonctionne, sauf dans un cas bien précis, quand j'ouvre un fichier dont le chemin est: "C:\Documents and Settings\Laurent\Bureau\apercu.bmp". Dans ce cas, il s'ouvre normalement la 1ère fois et puis si j'essaye de réouvrir la boite de dialogue le programme quitte dés que je place le curseur sur ce fichier. Il quitte instantanément, on drait qu'un message d'erreur apparaît mais on a pas le temps de la voir.

Voici le code de cette fonction:

  1. char *OpenFileDialog( char *szTitle, char *szDefExtention, char *szFilters )
  2. {
  3. if ( !szTitle || !szFilters )
  4. return NULL;
  5.  
  6. OPENFILENAME OpenFileName;
  7.  
  8. char szPath[ _MAX_PATH ] = "";
  9. char szFile[ _MAX_FNAME ] = "";
  10.  
  11. ZeroMemory( &OpenFileName, sizeof( OPENFILENAME ) );
  12.  
  13. OpenFileName.lStructSize = sizeof( OPENFILENAME );
  14. OpenFileName.hwndOwner = hWndMain;
  15. OpenFileName.hInstance = hInstance;
  16. OpenFileName.lpstrFilter = szFilters;
  17. OpenFileName.lpstrDefExt = szDefExtention;
  18. OpenFileName.lpstrFile = szPath;
  19. OpenFileName.nMaxFile = _MAX_PATH;
  20. OpenFileName.lpstrInitialDir = "levelcraft";
  21. OpenFileName.lpstrFileTitle = szFile;
  22. OpenFileName.nMaxFileTitle = _MAX_FNAME + _MAX_EXT;
  23. OpenFileName.lpstrTitle = szTitle;
  24. OpenFileName.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  25.  
  26. // Show the open file dialog
  27. if ( GetOpenFileName( &OpenFileName ) && szPath )
  28. {
  29. char *szFileName = new char[ strlen( szPath ) + 1 ];
  30.  
  31. strcpy( szFileName, szPath );
  32.  
  33. return szFileName;
  34. }
  35.  
  36. return NULL;
  37. }


Si quelqu'un trouve le problème, moi j'ai tout regarder je vois pas ce qui ne vas pas dans mon code...

Merci

Autres pages sur : getopenfilename probleme

a b L Programmation
28 Novembre 2008 21:54:06

EDIT: Bon, j'avais pas vu que tu avais fait un new quand j'ai commencé à répondre, alors, même si je pense que faire une allocation dynamique dans une telle fonction est une erreur de conception, ce qui est en italique ne te concerne pas (je le laisse pour info).

En ligne 29, tu crées une chaine sur la pile, donc ça ne peut pas marcher.
En C lorsque tu as des blocs entre accolades, tu définis des contextes qui sont empilés dans une pile lorsque les blocs s'emboitent (en ligne 29, sur la pile, tu as le contexte de la fonction et le contexte du if). Lorsque l'exécution arrive à la fin d'un bloc, son contexte est dépilé, et donc toutes les variables crées dans le contexte sont "détruites".
En ligne 29, tu crées ta chaine dans le contexte du if, tu retournes le pointeur de la chaine crées sur la pile, puis tu détruis la chaine. Donc, tu retournes un pointeur qui pointe sur des données qui n'existent plus
En fait, par "détruites", les données ne sont pas réellement effacées, c'est juste le pointeur de pile (registre SP = Stack Pointer) qui est déplacé, donc en théorie, en mémoire, le pointeur indique toujours les données, c'est ce qui explique que ça fonctionne la première fois. Seulement, lorsque lors de l'exécution, on ajoute des données dans la pile (par un nouveau contexte ou une nouvelle variable déclarée), et là on écrase les données indiquée par le pointeur, ce qui peut expliquer un crash lors du second passage.
Ton OpenFile dialog ne doit pas utiliser un char* en sortie, car tu ne retournes qu'une copie du pointeur et pas des données.
La solution idéale est que l'appelant de la fonction fourni un buffer déjà alloué à la fonction et lui indique la taille allouée. La fonction se contente donc de copier le résultat dans le buffer prévu.
Ensuite pour être pratrique, tu peux retourner le buffer de la fonction ou null s'il y a un problème (ou que l'utilisateur a annulé).


Donc pour ton problème, c'est peut-être uns mauvaise gestion du buffer retourné par ta fonction. Est-ce que tu sais sur quelle ligne précisément ton programme crash (en mode debug) ?
4 Décembre 2008 14:51:16

Merci pour ta superbe explication je comprends mieux!

Je ne sais pas sur quelle ligne ça plante exactement, j'ai essayé de savoir.

Mais maintenant je pourrai corriger le bug sans problèmes.

En fait, je pensais que je pouvais faire ça parce que j'avais allouer l'espace mémoire et que je revoyait l'adresse avant qu'elle soit détruite par la fin du scope...
a b L Programmation
4 Décembre 2008 20:18:26

Non justement, c'est pour ça que j'ai mis en italique, parce que tu as justement alloué la mémoire correctement. Avec le new, l'objet reste valide en dehors de la fonction.
En fait au début je ne pensais pas que tu utilisais le new, car c'est l'erreur classique. :) 
Mon explication était valide que si tu retournais directement szPath avant de faire une copie.

Sinon, ton réel problème ne vient probablement pas de cette fonction. mais de l'appelant. Il faut que tu vérifie tout dans ce qui fait revenir dans la fonction, c'est pour ça que tu devrais passer en mode debug ;) 
Tom's guide dans le monde
  • Allemagne
  • Italie
  • Irlande
  • Royaume Uni
  • Etats Unis
Suivre Tom's Guide
Inscrivez-vous à la Newsletter
  • ajouter à twitter
  • ajouter à facebook
  • ajouter un flux RSS