Transport d'une dll de eVC++ 3.0 en eVC++ 4.0

Résolu
PSylvie Messages postés 16 Date d'inscription lundi 12 juillet 2004 Statut Membre Dernière intervention 13 août 2004 - 5 août 2004 à 12:08
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019 - 13 août 2004 à 12:01
Bonjour,

Je possède une dll sous eVC++ 3.0 qui fonctionne parfaitement. Cependant, j'ai écrit une application sous eVC++ 4.0. qui a besoin de cette dll. Si je transporte la dll en eVC++ 4.0, elle plante (violation d'accès). Par contre, mon application eVC++4.0 fonctionne très bien avec la dll sous eVC++3.0!!! Quelles sont les différences entre eVC++ 3.0 et 4.0 qui font que ma dll ne fonctionne pas sur 4.0? Quelqu'un peut-il m'aider? Merci d'avance.
Sylvie

5 réponses

PSylvie Messages postés 16 Date d'inscription lundi 12 juillet 2004 Statut Membre Dernière intervention 13 août 2004 2
6 août 2004 à 10:07
Bonjour,

Merci pour le conseil mais mon problème est résolu. J'explique ici pourquoi cela ne fonctionnait pas au cas où quelqu'un rencontrerait un problème similaire. (Je travaille sur Smartphone 2003, pas sur PPC ;-) )

C'est en fait une fonction « memset » qui faisait planter l'application. Il semblerait que cette fonction memset ne fonctionne pas correctement sur des adresses qui ne sont pas alignées sur 4 bytes. Cependant, le compilateur C génère ce genre d'adresses, ce qui cause le plantage de la fonction memset. Cela fonctionne très bien si le code est compilé en C++. Pour contourner ce problème, il a fallu insérer un champ supplémentaire dans la structure sur laquelle travaillait la fonction memset pour « forcer » à aligner les adresses sur 4 bytes (une autre solution consisterait à créer sa propre fonction memset).

J'espère que cette explication pourra aider d'autres personnes?
Sylvie
3
neo_00110010101 Messages postés 360 Date d'inscription samedi 27 septembre 2003 Statut Membre Dernière intervention 30 mai 2006
5 août 2004 à 13:38
Salut,

Tu auras beaucoup de réponses à ton problème ici :
http://www.codeppc.com/forum/index.php

Car cela concerne le dev sur ppc non ? (vive les ppc ^^)

s~^"°¹~·-."z neo_00110010101 z".-·~¹°"^~s
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
6 août 2004 à 15:29
Depuis le temps que je repete a tout le monde d'aligner correctement les donnes d'une structure. Voici une belle demo de cette necessite.
Je retiens l'URL de ce post pour y renvoyer ceux qui douteraient de l'utilite.

ciao...
BruNews, Admin CS, MVP Visual C++
0
PSylvie Messages postés 16 Date d'inscription lundi 12 juillet 2004 Statut Membre Dernière intervention 13 août 2004 2
13 août 2004 à 11:42
Bonjour,

J'ai beau aligner mes données correctement le compilateur ne le respecte pas. J'explique ici pourquoi la fonction "memset" plante :

Le vrai coupable est enfin démasqué : le compilateur !! Preuves à l'appui?

Voici le bout de code qui plante :

------------------------------------------------------------------------------------------------------------
#define MAX_INFO_LENGTH 40

typedef struct
{
char *pszProcessedText;
unsigned short u16Duration;
char szLastWord[MAX_INFO_LENGTH];
} IVX_TTS_Sentence_Data;

typedef struct
{
long s32Id;
void *pvTtsData;
IVX_TTS_Sentence_Data SentenceData;
long a;
} IVX_TTS_Data;

/* Small test function */
void test()
{
IVX_TTS_Data* data;
ErrorMessage(TEXT("Creates structures"), NULL,0,0);

data=(IVX_TTS_Data*)malloc(sizeof(IVX_TTS_Data));

ErrorMessage(TEXT("adress of data->SentenceData.szLastWord"),NULL,(long)data->SentenceData.szLastWord,2);
memset(data->SentenceData.szLastWord, 0, MAX_INFO_LENGTH*sizeof (char)); //Plante ici
ErrorMessage(TEXT("It crashed ??? or not ???"), 0,0,0);
/* Never goes here:
When compiling in C, for ARMV4 -> it generates wrong ARM mnemonics!!!! */
free (data);
}
------------------------------------------------------------------------------------------------------------

Voici le bout de code assembleur généré en ce qui concerne le « memset » et la fonction « ErrorMessage » qui suit (et qui n'est jamais exécutée vu que le programme plante au memset) :

------------------------------------------------------------------------------------------------------------
; 57 : memset(data->SentenceData.szLastWord, 0, MAX_INFO_LENGTH*sizeof (char)/*data->SentenceData.szLastWord)*/);
; 58 : ErrorMessage(TEXT("It crashed ??? or not ???"), 0,0,0);

ldr r0, [pc, #0x44] //ErrorMessage
mov r3, #0 //Memset
str r3, [r4, #0xE] //Memset
mov r2, #0 //ErrorMessage
str r3, [r4, #0x12] //Memset
mov r1, #0 //ErrorMessage
str r3, [r4, #0x16] //Memset
str r3, [r4, #0x1A] //Memset
str r3, [r4, #0x1E] //Memset
str r3, [r4, #0x22] //Memset
str r3, [r4, #0x26] //Memset
str r3, [r4, #0x2A] //Memset
str r3, [r4, #0x2E] //Memset
str r3, [r4, #0x32] //Memset
mov r3, #0 //ErrorMessage
bl ErrorMessage //ErrorMessage
------------------------------------------------------------------------------------------------------------

C'est ce qu'on obtient quand l'optimisation est haute (/O2) : la fonction « memset » est remplacée par une suite d'instructions « str » visant à mettre à 0 le champ « szLastWord » de la structure (ce qui est le but de la fonction « memset » !). Plantage dans ce cas?
Par contre, si l'optimisation est basse (/O1), le code assembleur correspondant est le suivant :

------------------------------------------------------------------------------------------------------------
; 57 : memset(data->SentenceData.szLastWord, 0, MAX_INFO_LENGTH*sizeof (char)/*data->SentenceData.szLastWord)*/);

mov r2, #0x28
mov r1, #0
mov r0, r4
bl memset

; 58 : ErrorMessage(TEXT("It crashed ??? or not ???"), 0,0,0);

ldr r0, [pc, #0x18]
mov r3, #0
mov r2, #0
mov r1, #0
bl ErrorMessage
------------------------------------------------------------------------------------------------------------

Là, pas d'optimisation de la fonction « memset », le compilateur décide de l'appeler telle quelle. Plus de plantage !!

Explications :

La fonction « str » a besoin, pour fonctionner correctement, d'adresses alignées sur 4 bytes. Si ce n'est pas le cas, l'adresse est arrondie inférieurement à un multiple de 4 !! (voir « Assembler Guide » de www.arm.com : http://www.arm.com/pdfs/DUI0204D_rvct_ct_ag.pdf)

Si l'optimisation est haute (/O2) et si le troisième paramètre de la fonction « memset » est un multiple de 4 (ce qui est le cas dans le programme ci-dessus : MAX_INFO_LENGTH=40), le compilateur décide d'optimiser le code en remplaçant la fonction « memset » par des instructions « str ». Par contre, si le troisième paramètre n'est pas un multiple de 4, le compilateur décide de faire directement appel à memset (comme si l'optimisation était basse /O1). C'est ce que l'on peut constater si on remplace le troisième paramètre de « memset » « MAX_INFO_LENGTH*sizeof (char) » par « (MAX_INFO_LENGTH-2)*sizeof (char) ».

Cependant, il se fait que la structure contient un « short » (« unsigned short u16Duration ») juste avant le champ utilisé dans « memset » (« char szLastWord[MAX_INFO_LENGTH] »). Dès lors, ce champ commence en une adresse non multiple de 4 (en r4 + #0xE, comme on peut le voir dans le code assembleur), l'adresse de ce champ n'est donc pas alignée sur 4 bytes. Le « paramètre » [r4, #0xE] n'est pas apprécié par l'instruction « str » qui l'arrondi inférieurement à un nombre multiple de 4. La mise à 0 faite par la première instruction « str » commence donc trop tôt (de 2 bytes, le paramètre [r4, #0xE] est remplacé par [r4, #0x10] qui ne correspond plus au début du champ à mettre à zéro) et cause le plantage de l'application.

En bref, lorsque le compilateur décide d'optimiser la fonction « memset » par des instructions « str », il ne vérifie que le fait que le troisième paramètre soit un multiple de 4 mais ne vérifie pas que le champ à mettre à 0 est aligné sur 4 bytes. Or, ce sont ces deux conditions qui sont nécessaires afin de pouvoir se servir proprement de l'instruction « str ».

Deux solutions :
1. Baisser le niveau d'optimisation du compilateur
2. Introduire dans la structure un autre « short » avant le champ szLastWord[MAX_INFO_LENGTH] pour que ce dernier soit bien aligné sur 4 bytes.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
13 août 2004 à 12:01
Mais c'est typique un cas de mauvaise construction de structure, les donnees ne sont pas alignees.
IVX_TTS_Sentence_Data DOIT avoir un 'short' de cadrage.

Pour aligner correct les donnees d'une struct:
- Placer les types les plus longs au debut et par ordre decroissant.
- Aligner chaque type sur un multiple de sa taille.
- Mettre octets de cadrage quand besoin et en finale jusque taille totale soit multiple de 4.

ciao...
BruNews, Admin CS, MVP Visual C++
0
Rejoignez-nous