 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Geoffrey Guest
|
Posted: Tue Jun 21, 2005 2:57 pm Post subject: [DEBUTANT] Invalid address specified to RtlValidateHeap |
|
|
Bonjour,
petite question sur l'utilisation des dlls
soit une DLL A et une DLL B
la DLL B contient une classe
class Classe_de_B
{
Classe_de_B();
const std::string get() { return "Chaine de B"; }
};
ainsi qu'une qu'une autre classe Proxy_B qui est un singleton et manipulant Classe_de_B
class Proxy_B : Singleton
{
Classe_de_B mMembre;
const std::string get() { return mMembre.get(); }
}
je declare egalement une fonction
extern "C" __declspec(dllexport) Proxy_B* Start()
{
return &Proxy_B::Instance();
}
maintenant dans une classe de la DLL A
si je fais
{
typedef Proxy_B* (*MyFunc)();
HMODULE handle = ::loadLibrary( B.dll );
MyFunct ptr = (myFunct)( ::GetProcAdress( handle, "Start" ) );
if ( ptr != NULL )
{
Proxy_B* proxyB = ptr();
assert( proxyB != NULL );
std::string chaine_a_probleme = proxyB->get();
// ici la chaine a probleme devrait contenir "Chaine de B", et c'est bien le cas
// le soucis est lors de la destruction de chaine_a_probleme
// j'ai ce genre d'erreur -> "Invalid address specified to RtlValidateHeap"
// visiblement "chaine_a_probleme" englobe un pointeur et non une copie de la chaine d'origine, pourquoi, comment y remedier ??
}
}
En fait dans mon projet la "classe_de_B" contient plusieurs fonctions retournant des chaines constantes, ca fonctionne avec certaine et pas avec d'autre ...
Je ne saisie pas bien la difference et je ne demande qu'a comprendre, donc si quelqu'un peut m'expliquer en detail merci d'avance ^^
PS: desole pour la presentation, j'espere que c'est assez clair ...
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Wed Jun 22, 2005 6:57 am Post subject: Re: Invalid address specified to RtlValidateHeap |
|
|
Geoffrey wrote:
| Quote: | petite question sur l'utilisation des dlls
soit une DLL A et une DLL B
la DLL B contient une classe
class Classe_de_B
{
Classe_de_B();
const std::string get() { return "Chaine de B"; }
};
ainsi qu'une qu'une autre classe Proxy_B qui est un singleton
et manipulant Classe_de_B
class Proxy_B : Singleton
{
Classe_de_B mMembre;
const std::string get() { return mMembre.get(); }
}
je declare egalement une fonction
extern "C" __declspec(dllexport) Proxy_B* Start()
{
return &Proxy_B::Instance();
}
maintenant dans une classe de la DLL A si je fais
{
typedef Proxy_B* (*MyFunc)();
HMODULE handle = ::loadLibrary( B.dll );
MyFunct ptr = (myFunct)( ::GetProcAdress( handle, "Start" ) );
if ( ptr != NULL )
{
Proxy_B* proxyB = ptr();
assert( proxyB != NULL );
std::string chaine_a_probleme = proxyB->get();
// ici la chaine a probleme devrait contenir "Chaine de B", et c'est bien le cas
// le soucis est lors de la destruction de chaine_a_probleme
// j'ai ce genre d'erreur -> "Invalid address specified to RtlValidateHeap"
// visiblement "chaine_a_probleme" englobe un pointeur et non unecopie de la chaine d'origine, pourquoi, comment y remedier ??
}
}
En fait dans mon projet la "classe_de_B" contient plusieurs
fonctions retournant des chaines constantes, ca fonctionne
avec certaine et pas avec d'autre ... Je ne saisie pas bien la
difference et je ne demande qu'a comprendre, donc si quelqu'un
peut m'expliquer en detail merci d'avance ^^
|
À vrai dire, ça dépend beaucoup de ta plateforme ; je fais la
même chose chez moi -- dans la configuration par défaut, au
moins, et en changeant les noms des fonctions à dlopen, dlsym --
et ça marche sans problème.
En fait, il y a plusieurs modèles différents en ce qui concerne
la façon de gerer les symboles lors des éditions de liens
dynamiques. Celui par défaut sous Windows fait que chaque DLL
est une unité en soi, bien isolée, et que si un symbole est
résolu dans l'objet dynamique, on utilise le symbole dans
l'objet dynamique, même si le même symbole existe par ailleurs.
C'est un modèle avec beaucoup d'avantages (c'est le modèle dont
je me sers le plus sous Unix, même s'il n'est pas le défaut là),
mais il existe un peu d'attention, pour ne pas avoir en double
des choses qui ne doivent pas être en double.
Dans ton cas, apparamment, ce qu'il y a en double, c'est
l'implémentation de malloc/free. Ce qui a comme conséquence
que libérer de la mémore dans un objet qui a été allouée dans un
autre ne marche pas. Et std::string, lui, utilise bien de la
mémore dynamique -- si un objet de type std::string est
construit dans un objet, et detruit dans un autre, tu risques
d'avoir de problèmes.
Ce qu'il faut faire, c'est de revoir comment tu as fait
l'édition de liens de tes objets dynamiques ; il faut faire en
sort que l'objet dynamique ne contient pas la bibliothèque de
base. La solution « standard » sous Unix, c'est que la
bibliothèque de base est elle-même un objet dynamique. Qui
serait forcement linké dès le démarrage du programme, parce que
même le code qui précède main en a besoin. Mais dans ce cas-ci,
linké avec un modèle qui expose tous les points d'entrée aux
bibliothèques qui seront linkées plus tard. Je sais que cette
solution fonctionne aussi sous Windows aussi, mais n'étant pas
spécialisé dans cette plateforme, je ne saurais pas te dire ce
qu'il faut réelement faire. Ce genre de question, il vaut mieux
la poser dans un groupe windows, où se trouve les spécialistes
Windows.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
|
|
| Back to top |
|
 |
Geoffrey Guest
|
Posted: Wed Jun 22, 2005 9:26 am Post subject: Re: Invalid address specified to RtlValidateHeap |
|
|
<kanze (AT) gabi-soft (DOT) fr> a écrit dans le message de news:
[email]1119423465.689708.179730 (AT) g47g2000cwa (DOT) googlegroups.com[/email]...
Geoffrey wrote:
| Quote: | À vrai dire, ça dépend beaucoup de ta plateforme ; je fais la
même chose chez moi -- dans la configuration par défaut, au
moins, et en changeant les noms des fonctions à dlopen, dlsym --
et ça marche sans problème.
En fait, il y a plusieurs modèles différents en ce qui concerne
la façon de gerer les symboles lors des éditions de liens
dynamiques. Celui par défaut sous Windows fait que chaque DLL
est une unité en soi, bien isolée, et que si un symbole est
résolu dans l'objet dynamique, on utilise le symbole dans
l'objet dynamique, même si le même symbole existe par ailleurs.
C'est un modèle avec beaucoup d'avantages (c'est le modèle dont
je me sers le plus sous Unix, même s'il n'est pas le défaut là),
mais il existe un peu d'attention, pour ne pas avoir en double
des choses qui ne doivent pas être en double.
Dans ton cas, apparamment, ce qu'il y a en double, c'est
l'implémentation de malloc/free. Ce qui a comme conséquence
que libérer de la mémore dans un objet qui a été allouée dans un
autre ne marche pas. Et std::string, lui, utilise bien de la
mémore dynamique -- si un objet de type std::string est
construit dans un objet, et detruit dans un autre, tu risques
d'avoir de problèmes.
Ce qu'il faut faire, c'est de revoir comment tu as fait
l'édition de liens de tes objets dynamiques ; il faut faire en
sort que l'objet dynamique ne contient pas la bibliothèque de
base. La solution « standard » sous Unix, c'est que la
bibliothèque de base est elle-même un objet dynamique. Qui
serait forcement linké dès le démarrage du programme, parce que
même le code qui précède main en a besoin. Mais dans ce cas-ci,
linké avec un modèle qui expose tous les points d'entrée aux
bibliothèques qui seront linkées plus tard. Je sais que cette
solution fonctionne aussi sous Windows aussi, mais n'étant pas
spécialisé dans cette plateforme, je ne saurais pas te dire ce
qu'il faut réelement faire. Ce genre de question, il vaut mieux
la poser dans un groupe windows, où se trouve les spécialistes
Windows.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
|
tout d'abord merci pour ta reponse James.
pour complement d'information, j'utilise VS7 sous WinXP.
Les erreurs n'apparaissent qu'en debug !
Dite moi si je me trompe, ce que j'ai compris ( ou crois avoir compris ),
lorsque windows charge une dll, il lui alloue un espace memoire a son usage
propre ( un heap ? ) ainsi toute variables/objets créé dans cet espace
memoire doit egalement etre detruit dans cet espace memoire ??
Donc si je pointe sur une donnée qui est alloue dans un autre heap et que je
tente de la detruire je m'expose au probleme que j'ai ci dessus, puisque les
adresses d'allocation sont faussées non ???
Sauf que dans mon cas je ne pointe sur rien, je pensais plutot que la
variable string locale contenait une copie de la chaine d'origine, et lorque
je regarde attentivement le contenus de cette variable, je m'apercoit quelle
pointe sur la ressource d'origine ... j'ai du raté des chose au niveau de la
construction d'un std::string car parfois la donnée est copié et dans
l'autre cas la donné est pointé.
Bizarrement j'ai resolu le probleme differement, mais je ne comprend pas
l'influence.
Dans ma solution, j'ai 3 projets, un exe, dll1, dll2.
l'exe charge la dll1 dynamiquement, la dll1 charge la dll2 ( et en chargera
aussi d'autre )
dans les option de compilation du projet les DLL avais comme indication
Multithreaded DLL et l'exe single-threaded, en passant les option de
compilation de l'exe sur multithreaded, je n'ai plus ces erreurs !!!???
Pourquoi cela ????
merci pour vos explications.
|
|
| Back to top |
|
 |
adebaene@club-internet.fr Guest
|
Posted: Wed Jun 22, 2005 9:39 am Post subject: Re: Invalid address specified to RtlValidateHeap |
|
|
Geoffrey a écrit :
| Quote: | Bonjour,
petite question sur l'utilisation des dlls
soit une DLL A et une DLL B
snip allocation dans une DLL et libération du pointeur dans une autre |
DLL>
James t'a déjà expliqué le problème en détail : tu utilises 2
copies de la CRT (les fonctions malloc et free notamment), une dans
chaque DLL. La CRT de la DLL B n'a pas connaissance des allocations
faites dans la DLL A et vice-versa.
La solution consiste à s'arranger pour que chaque DLL se lie avec une
version DLL de la CRT : cette CRT ne sera chargée qu'une seule fois
dans tout ton processus, et donc les DSLLs A et B partageront le même
allocateur. Comment faire cela dépend de ton environnement de
développement exact (sous Visual, regardes les flags /MD et /MDd du
compilateur).
Arnaud
|
|
| Back to top |
|
 |
Geoffrey Guest
|
Posted: Wed Jun 22, 2005 9:56 am Post subject: Re: Invalid address specified to RtlValidateHeap |
|
|
"Geoffrey" <gbaudin2 (AT) wanadoo (DOT) fr> a écrit dans le message de news:
42b92ecb$0$1249$8fcfb975 (AT) news (DOT) wanadoo.fr...
| Quote: |
[email]kanze (AT) gabi-soft (DOT) fr[/email]> a écrit dans le message de news:
[email]1119423465.689708.179730 (AT) g47g2000cwa (DOT) googlegroups.com[/email]...
Geoffrey wrote:
À vrai dire, ça dépend beaucoup de ta plateforme ; je fais la
même chose chez moi -- dans la configuration par défaut, au
moins, et en changeant les noms des fonctions à dlopen, dlsym --
et ça marche sans problème.
En fait, il y a plusieurs modèles différents en ce qui concerne
la façon de gerer les symboles lors des éditions de liens
dynamiques. Celui par défaut sous Windows fait que chaque DLL
est une unité en soi, bien isolée, et que si un symbole est
résolu dans l'objet dynamique, on utilise le symbole dans
l'objet dynamique, même si le même symbole existe par ailleurs.
C'est un modèle avec beaucoup d'avantages (c'est le modèle dont
je me sers le plus sous Unix, même s'il n'est pas le défaut là),
mais il existe un peu d'attention, pour ne pas avoir en double
des choses qui ne doivent pas être en double.
Dans ton cas, apparamment, ce qu'il y a en double, c'est
l'implémentation de malloc/free. Ce qui a comme conséquence
que libérer de la mémore dans un objet qui a été allouée dans un
autre ne marche pas. Et std::string, lui, utilise bien de la
mémore dynamique -- si un objet de type std::string est
construit dans un objet, et detruit dans un autre, tu risques
d'avoir de problèmes.
Ce qu'il faut faire, c'est de revoir comment tu as fait
l'édition de liens de tes objets dynamiques ; il faut faire en
sort que l'objet dynamique ne contient pas la bibliothèque de
base. La solution « standard » sous Unix, c'est que la
bibliothèque de base est elle-même un objet dynamique. Qui
serait forcement linké dès le démarrage du programme, parce que
même le code qui précède main en a besoin. Mais dans ce cas-ci,
linké avec un modèle qui expose tous les points d'entrée aux
bibliothèques qui seront linkées plus tard. Je sais que cette
solution fonctionne aussi sous Windows aussi, mais n'étant pas
spécialisé dans cette plateforme, je ne saurais pas te dire ce
qu'il faut réelement faire. Ce genre de question, il vaut mieux
la poser dans un groupe windows, où se trouve les spécialistes
Windows.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
tout d'abord merci pour ta reponse James.
pour complement d'information, j'utilise VS7 sous WinXP.
Les erreurs n'apparaissent qu'en debug !
Dite moi si je me trompe, ce que j'ai compris ( ou crois avoir compris ),
lorsque windows charge une dll, il lui alloue un espace memoire a son
usage propre ( un heap ? ) ainsi toute variables/objets créé dans cet
espace memoire doit egalement etre detruit dans cet espace memoire ??
Donc si je pointe sur une donnée qui est alloue dans un autre heap et que
je tente de la detruire je m'expose au probleme que j'ai ci dessus,
puisque les adresses d'allocation sont faussées non ???
Sauf que dans mon cas je ne pointe sur rien, je pensais plutot que la
variable string locale contenait une copie de la chaine d'origine, et
lorque je regarde attentivement le contenus de cette variable, je
m'apercoit quelle pointe sur la ressource d'origine ... j'ai du raté des
chose au niveau de la construction d'un std::string car parfois la donnée
est copié et dans l'autre cas la donné est pointé.
Bizarrement j'ai resolu le probleme differement, mais je ne comprend pas
l'influence.
Dans ma solution, j'ai 3 projets, un exe, dll1, dll2.
l'exe charge la dll1 dynamiquement, la dll1 charge la dll2 ( et en
chargera aussi d'autre )
dans les option de compilation du projet les DLL avais comme indication
Multithreaded DLL et l'exe single-threaded, en passant les option de
compilation de l'exe sur multithreaded, je n'ai plus ces erreurs !!!???
Pourquoi cela ????
merci pour vos explications.
|
Autant pour moi je me suis trompé, passer l'exe en multi threading n'a rien
changé !!!!
je ne passais simplement plus dans la section de code a probleme :p ...
|
|
| Back to top |
|
 |
Geoffrey Guest
|
Posted: Wed Jun 22, 2005 10:07 am Post subject: Re: Invalid address specified to RtlValidateHeap |
|
|
<adebaene (AT) club-internet (DOT) fr> a écrit dans le message de news:
[email]1119433188.046138.311820 (AT) f14g2000cwb (DOT) googlegroups.com[/email]...
Geoffrey a écrit :
| Quote: | Bonjour,
petite question sur l'utilisation des dlls
soit une DLL A et une DLL B
snip allocation dans une DLL et libération du pointeur dans une autre |
DLL>
James t'a déjà expliqué le problème en détail : tu utilises 2
copies de la CRT (les fonctions malloc et free notamment), une dans
chaque DLL. La CRT de la DLL B n'a pas connaissance des allocations
faites dans la DLL A et vice-versa.
La solution consiste à s'arranger pour que chaque DLL se lie avec une
version DLL de la CRT : cette CRT ne sera chargée qu'une seule fois
dans tout ton processus, et donc les DSLLs A et B partageront le même
allocateur. Comment faire cela dépend de ton environnement de
développement exact (sous Visual, regardes les flags /MD et /MDd du
compilateur).
Arnaud
-----------------------------------------------------------------------------------
En effet, ce que tu dis rejoins la solution que j'ai trouvé sur un forum a
savoir un probleme avec les flag /MD /MDd ...
par defaut les dll créé par l'assistant avais les FLAGS Multi threaded
et l'exe single Threaded
j'ai donc testé de passer l'exe en Multi threaded comme les dll mais sans
succes ...
Apres plusieurs essai, j'ai trouve une configuration qui fonctionne a savoir
les DLL en Multi threaded DLL ( sa semble logique )
et l'exe en multi threaded
cette fois je n'ai plus ces problemes d'allocation memoire, mais je n'ai
toujours pas compris ce que modifie ces flags et a quoi ils correspondent,
si tu pouvais m'eclairer un peu, je te remercie d'avance.
|
|
| Back to top |
|
 |
Arnaud Debaene Guest
|
Posted: Wed Jun 22, 2005 7:12 pm Post subject: Re: Invalid address specified to RtlValidateHeap |
|
|
Geoffrey wrote:
| Quote: |
En effet, ce que tu dis rejoins la solution que j'ai trouvé sur un
forum a savoir un probleme avec les flag /MD /MDd ...
par defaut les dll créé par l'assistant avais les FLAGS Multi threaded
et l'exe single Threaded
j'ai donc testé de passer l'exe en Multi threaded comme les dll mais
sans succes ...
Apres plusieurs essai, j'ai trouve une configuration qui fonctionne a
savoir les DLL en Multi threaded DLL ( sa semble logique )
et l'exe en multi threaded
Perdu : c'est *tous* les modules (exe et dlls) compilés soit tous avec /MD |
(en release), soit tous avec /MDd (en debug) : l'exe aussi doit utiliser la
version DLL de la CRT s'il veut pouvoir libérer des pointeurs alloués par
une DLL, ou vice-versa.
| Quote: | cette fois je n'ai plus ces problemes d'allocation memoire, mais je
n'ai toujours pas compris ce que modifie ces flags et a quoi ils
correspondent, si tu pouvais m'eclairer un peu, je te remercie d'avance.
|
Le code de malloc, free, fopen, qsort, etc... bref tout les fonctions de la
CRT, il est bien quelque part dans ton programme! Tu as 2 options :
- chaque module (exe ou dll) embarque sa propre copie du code de la CRT. Ca
signifie que tu as plusieurs instances de la CRT dans ton programme (1 par
module). L'instance de la DLL A connait (par exemple) tous les pointeurs qui
ont été alloués avec malloc dans la DLL A, et ses pointeurs peuvent donc
être libérés avec free dans la DLL A. Par contre, un pointeur alloué par le
malloc de la DLL B (ou de l'exe) est inconnu de la CRT de la DLL A, et si tu
essaies de faire un free dessus dans A, tu es bon pour le plantage (ce que
tu as). Sous Visual, on obtient ce fonctionnement avec /ML, /MLd, /MR ou
/MTd
- chaque module n'embarque pas le code de la CRT mausutilise une version de
la CRT dans une DLL (msvcrt.dll et ses variantes sous VC). Comme une DLL
n'est chargée qu'une seule fois par processus, tous les modules partagent
donc une seule CRT, et tu peux librement allouer dans un module et libéré
dans l'autre. Avec VC, tu obitens cete configuration avec /MD ou /MDd. Le
défaut de cette solution, c'est qu'il faut redistribuer la/les DLL(s) de la
CRT (msvcrt.dll et ses petits copains) avec ton application.
(PS : ce principe s'applique non seulement à la mémoire, mais à tout l'état
de la CRT : les FILE* ouverts, l'état courant de qsort, de strtok, etc...)
Arnaud
|
|
| Back to top |
|
 |
Geoffrey Guest
|
Posted: Wed Jun 22, 2005 9:53 pm Post subject: Re: Invalid address specified to RtlValidateHeap |
|
|
"Arnaud Debaene" <adebaene (AT) club-internet (DOT) fr> a écrit dans le message de
news: 42b9b7f8$0$21841$626a14ce (AT) news (DOT) free.fr...
| Quote: | Geoffrey wrote:
En effet, ce que tu dis rejoins la solution que j'ai trouvé sur un
forum a savoir un probleme avec les flag /MD /MDd ...
par defaut les dll créé par l'assistant avais les FLAGS Multi threaded
et l'exe single Threaded
j'ai donc testé de passer l'exe en Multi threaded comme les dll mais
sans succes ...
Apres plusieurs essai, j'ai trouve une configuration qui fonctionne a
savoir les DLL en Multi threaded DLL ( sa semble logique )
et l'exe en multi threaded
Perdu : c'est *tous* les modules (exe et dlls) compilés soit tous avec /MD
(en release), soit tous avec /MDd (en debug) : l'exe aussi doit utiliser
la version DLL de la CRT s'il veut pouvoir libérer des pointeurs alloués
par une DLL, ou vice-versa.
cette fois je n'ai plus ces problemes d'allocation memoire, mais je
n'ai toujours pas compris ce que modifie ces flags et a quoi ils
correspondent, si tu pouvais m'eclairer un peu, je te remercie d'avance.
Le code de malloc, free, fopen, qsort, etc... bref tout les fonctions de
la CRT, il est bien quelque part dans ton programme! Tu as 2 options :
- chaque module (exe ou dll) embarque sa propre copie du code de la CRT.
Ca signifie que tu as plusieurs instances de la CRT dans ton programme (1
par module). L'instance de la DLL A connait (par exemple) tous les
pointeurs qui ont été alloués avec malloc dans la DLL A, et ses pointeurs
peuvent donc être libérés avec free dans la DLL A. Par contre, un pointeur
alloué par le malloc de la DLL B (ou de l'exe) est inconnu de la CRT de la
DLL A, et si tu essaies de faire un free dessus dans A, tu es bon pour le
plantage (ce que tu as). Sous Visual, on obtient ce fonctionnement avec
/ML, /MLd, /MR ou /MTd
- chaque module n'embarque pas le code de la CRT mausutilise une version
de la CRT dans une DLL (msvcrt.dll et ses variantes sous VC). Comme une
DLL n'est chargée qu'une seule fois par processus, tous les modules
partagent donc une seule CRT, et tu peux librement allouer dans un module
et libéré dans l'autre. Avec VC, tu obitens cete configuration avec /MD ou
/MDd. Le défaut de cette solution, c'est qu'il faut redistribuer la/les
DLL(s) de la CRT (msvcrt.dll et ses petits copains) avec ton application.
(PS : ce principe s'applique non seulement à la mémoire, mais à tout
l'état de la CRT : les FILE* ouverts, l'état courant de qsort, de strtok,
etc...)
Arnaud
|
C'est beaucoup plus clair dans ma tête a present, reste a savoir combien de
temps cela y demeurera ^^
Merci encore pour ces explications.
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Thu Jun 23, 2005 8:56 am Post subject: Re: Invalid address specified to RtlValidateHeap |
|
|
Geoffrey wrote:
| Quote: | kanze (AT) gabi-soft (DOT) fr> a écrit dans le message de news:
[email]1119423465.689708.179730 (AT) g47g2000cwa (DOT) googlegroups.com[/email]...
Geoffrey wrote:
Ce qu'il faut faire, c'est de revoir comment tu as fait
l'édition de liens de tes objets dynamiques ; il faut faire
en sort que l'objet dynamique ne contient pas la bibliothèque
de base. La solution « standard » sous Unix, c'est que la
bibliothèque de base est elle-même un objet dynamique. Qui
serait forcement linké dès le démarrage du programme, parce
que même le code qui précède main en a besoin. Mais dans ce
cas-ci, linké avec un modèle qui expose tous les points
d'entrée aux bibliothèques qui seront linkées plus tard. Je
sais que cette solution fonctionne aussi sous Windows aussi,
mais n'étant pas spécialisé dans cette plateforme, je ne
saurais pas te dire ce qu'il faut réelement faire. Ce genre
de question, il vaut mieux la poser dans un groupe windows,
où se trouve les spécialistes Windows.
pour complement d'information, j'utilise VS7 sous WinXP. Les
erreurs n'apparaissent qu'en debug !
|
C-à-d éventuellement que tu ne les detecte qu'en mode debug. Si
le choix de mode debug ne change pas la façon de linker, il est
probable que les erreurs y sont aussi en mode release, mais
qu'elles se présentent sous la forme des fuites de mémoire,
voire des corruptions de l'arène de la mémoire libre, qui
provoqueront les erreurs bizarres plus tard si le programme
continuait à tourner.
| Quote: | Dite moi si je me trompe, ce que j'ai compris ( ou crois avoir
compris ), lorsque windows charge une dll, il lui alloue un
espace memoire a son usage propre ( un heap ? ) ainsi toute
variables/objets créé dans cet espace memoire doit egalement
etre detruit dans cet espace memoire ??
|
C'est un peu plus compliqué que ça en ce qui concerne la mémoire
dynamique. En ce qui concerne le système, ça lui est égal, je
crois, qui alloue de la mémoire qui va devenir le heap. (S'il
fonctionne comme Unix, d'ailleurs, au niveau système, une fois
alloué, la mémoire ne sera plus libérée par le processus.) Le
problème, c'est que pour gérer le heap, malloc/free utilise un
certain nombre de variables statiques ; ce sont ces variables
qui se retrouvent dupliquées chaque fois malloc/free sont
chargés. À travers ces variables, malloc/free savent où se
trouve la mémoire qu'ils gèrent, quels blocs sont libres ou
alloués, etc. Or, en supposant deux instances distinctes de ces
variables, si tu alloues à partir d'une instances, et libre dans
l'autre, le bloc que tu libres ne se trouve pas dans la mémoire
gérée par l'instance où tu l'as libéré. En mode debug,
apparamment, free fait des vérifications -- si la mémoire n'a
pas été allouée par lui, il signale tout de suite une erreur. En
mode non debug, ces vérifications n'ont pas lieu. Mais free va
quand même essayer de libérer un bloc qui ne lui appartient, ce
qui pourrait très bien provoquer des incohérences dans les
données.
| Quote: | Donc si je pointe sur une donnée qui est alloue dans un autre
heap et que je tente de la detruire je m'expose au probleme
que j'ai ci dessus, puisque les adresses d'allocation sont
faussées non ???
|
Pas les adresses. Mais les variables statiques qu'utilise le
free ne correspond pas à celles qui ont servi lors de son
allocation, qui sont celles où le bloc est réelement geré. Ce
qui peut mener à des incohérences.
| Quote: | Sauf que dans mon cas je ne pointe sur rien, je pensais plutot
que la variable string locale contenait une copie de la chaine
d'origine, et lorque je regarde attentivement le contenus de
cette variable, je m'apercoit quelle pointe sur la ressource
d'origine ... j'ai du raté des chose au niveau de la
construction d'un std::string car parfois la donnée est copié
et dans l'autre cas la donné est pointé.
|
La norme ne dit rien sur quand std::string copie, et quand il ne
copie pas. Certaines implémentations -- celles de g++ ou de VC++
6, par exemple, utilise une politique dite « copy on write »
(COW) -- quand tu copies ou que tu affectes une chaîne, il ne
copie qu'un pointeur, et ne font une copie profond des données
que quand il y a risque de modification. D'autres (dont, je
crois, VC++ 7.x) font systèmatiquement une copie profonde -- en
général, l'objet lui-même contient une petite cache, de façon
qu'on n'alloue dynamiquement que quand la chaîne dépasse une
certaine taille.
En plus, il y a des optimisations des copies permises par la
norme. Quand une fonction renvoie une chaîne, la chaîne est créé
(construit) dans la fonction ; théoretiquement, elle serait
detruite à la fin de l'expression où se trouve l'appel (et donc,
dans la DLL où a eu lieu l'appel). En fait, le compilateur a le
droit de fusionner plusieurs instances dans certains cas, ce qui
fait que l'appel du destructeur à la fin de l'expression n'est
pas certain.
Comme j'ai dit avant, il est essentiel que tu n'aies qu'une
seule instance de malloc/free dans ton programme : soit dans le
programme principal (le .exe), soit dans un objet dynamique à
part qui n'est chargé qu'une seule fois, au demarrage. Je ne
connais bien qu'Unix, mais aussi sous Windows, il doit exister
l'équivalent à libc.so (un DLL avec toutes les fonctions de
base, ou du langage C, ou de l'API système), et une possibilité
de linker les DLL contre cet objet, sans l'incorporer de force
dans le DLL. Il faudrait démander dans un groupe Windows quelles
options il faut donner au linker pour qu'il le fasse.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Thu Jun 23, 2005 9:08 am Post subject: Re: Invalid address specified to RtlValidateHeap |
|
|
Arnaud Debaene wrote:
| Quote: | - chaque module n'embarque pas le code de la CRT mausutilise
une version de la CRT dans une DLL (msvcrt.dll et ses
variantes sous VC). Comme une DLL n'est chargée qu'une seule
fois par processus, tous les modules partagent donc une seule
CRT, et tu peux librement allouer dans un module et libéré
dans l'autre. Avec VC, tu obitens cete configuration avec /MD
ou /MDd. Le défaut de cette solution, c'est qu'il faut
redistribuer la/les DLL(s) de la CRT (msvcrt.dll et ses petits
copains) avec ton application.
|
Ce qui explique pourquoi ce comportement n'est pas le défaut.
Est-ce qu'on a droit de distribuer ce DLL avec son programme ?
Ou est-ce qu'il faut une license spéciale, ou que l'utilisateur
du programme ait une license supplémentaire pour utliser cette
DLL.
J'ai l'habitude de Unix, ou libc.so fait partie du système -- il
n'existe pas de machine Unix où il n'est pas présent. Et où
d'utliser est le défaut. D'ailleurs, est-ce qu'il ne serait pas
présente aussi sur toute machine Windows. J'ai du mal à croire
qu'il ne sert pas déjà dans les utilitaires de système.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
|
|
| Back to top |
|
 |
Arnaud Debaene Guest
|
Posted: Thu Jun 23, 2005 5:19 pm Post subject: Re: Invalid address specified to RtlValidateHeap |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
| Quote: | Arnaud Debaene wrote:
- chaque module n'embarque pas le code de la CRT mausutilise
une version de la CRT dans une DLL (msvcrt.dll et ses
variantes sous VC). Comme une DLL n'est chargée qu'une seule
fois par processus, tous les modules partagent donc une seule
CRT, et tu peux librement allouer dans un module et libéré
dans l'autre. Avec VC, tu obitens cete configuration avec /MD
ou /MDd. Le défaut de cette solution, c'est qu'il faut
redistribuer la/les DLL(s) de la CRT (msvcrt.dll et ses petits
copains) avec ton application.
Ce qui explique pourquoi ce comportement n'est pas le défaut.
Est-ce qu'on a droit de distribuer ce DLL avec son programme ?
Oui, elle fait partie des "redistribuables" de VC. Le problème dans le |
passé, c'est que les différentes versions de cette DLL avaient tendance à se
marcher dessus si elles étaient installées dans le répertoire système (et
malheureusement, elle l'était souvent). Récemment, le mécanisme de
"side-by-side" a simplifié ce problème.
Pour couronner le tout, jusqu'à maintenent, la CRT était fournie en version
multithread-safe et monothread (sans synchronisation). La version monothread
a enfin été abandonnée dans VC8.
| Quote: | Ou est-ce qu'il faut une license spéciale, ou que l'utilisateur
du programme ait une license supplémentaire pour utliser cette
DLL.
Non non, pas de problème... |
| Quote: | J'ai l'habitude de Unix, ou libc.so fait partie du système -- il
n'existe pas de machine Unix où il n'est pas présent. Et où
d'utliser est le défaut. D'ailleurs, est-ce qu'il ne serait pas
présente aussi sur toute machine Windows. J'ai du mal à croire
qu'il ne sert pas déjà dans les utilitaires de système.
Le problème c'est que les différents compilateurs et les différentes |
versions d'un compilateur donné n'utilisent pas forcémment la même DLL. Le
système vient avec une version de msvcrt.dll (la version correspondant à la
version d VC utilisée pour compiler l'OS), mais ce n'est pas toujours la
version demandée par les applis.
Comment ca se passe sous Unix? La CRT n'est jamais mise-à-jour? Je suppose
que toutes les applis, compilées avec tous les compilateurs, doivent
utiliser la même CRT...
Arnaud
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Fri Jun 24, 2005 8:34 am Post subject: Re: Invalid address specified to RtlValidateHeap |
|
|
Arnaud Debaene wrote:
[...]
| Quote: | J'ai l'habitude de Unix, ou libc.so fait partie du système
-- il n'existe pas de machine Unix où il n'est pas présent.
Et où d'utliser est le défaut. D'ailleurs, est-ce qu'il ne
serait pas présente aussi sur toute machine Windows. J'ai du
mal à croire qu'il ne sert pas déjà dans les utilitaires de
système.
Le problème c'est que les différents compilateurs et les
différentes versions d'un compilateur donné n'utilisent pas
forcémment la même DLL. Le système vient avec une version de
msvcrt.dll (la version correspondant à la version d VC
utilisée pour compiler l'OS), mais ce n'est pas toujours la
version demandée par les applis.
Comment ca se passe sous Unix ? La CRT n'est jamais
mise-à-jour ? Je suppose que toutes les applis, compilées avec
tous les compilateurs, doivent utiliser la même CRT...
|
Il y a en fait deux possibilités.
En ce qui concerne libc.so, c'est simple : l'API est normalisée.
On peut y ajouter, mais on ne change ni n'ôte jamais l'existant
(dans l'API). Du coup, on doit pouvoir utiliser n'importe quel
version à partir d'un certain point -- en théorie, en tout cas,
mais aussi en pratique, prèsque toujours. Ça dépend aussi un peu
de comment on code. Par exemple, quand je code au niveau
système, j'utilise surtout les docs de la norme Posix, et non
les docs Solaris. Parce que c'est vrai que si j'écris pour
Solaris 8, il y a de fortes chances que ça ne marche pas avec
Solaris 7.
Ici, en fait, c'est la justification même de l'objet linké
dynamiquement. L'interface réele du système peut évoluer ; c'est
la rôle de la bibliothèque libc.so (et libsocket.so, et...)
d'adapter l'API normalisée à l'interface du système du jours. De
cette façon, le même code applicatif tourne sur Solaris 7,
Solaris 8 et Solaris 9, malgré des modifications dans
l'interface système. Il existe même un objet dynamique pour
simuler l'interface Sun OS 4.x (un Unix UCB, très différent des
Solaris et d'autres System V). Pour citer le manuel de Solaris
(« Linker and Libraries Guide » -- c'est déjà signifiant que ce
manuel fait partie de la documentation système, et non de la
documentation d'un environement de développement quelconque) :
By separating an application from the services of standard
libraries, dynamic linking also increases the portability
and extensibility of an application. This separation between
the interface of a service and its implementation enables
the system to evolve while maintaining application
stability, and is a crucial factor in providing an
application binary interface (ABI). Dynamic linking is the
preferred compilation method for Solaris applications.
En plus, Unix supporte (de façon assez primitive, à travers des
conventions de nommage) une espèce de gestion de version. Du
coup, si ton programme a besoin d'une version spécifique, il
peut l'exiger, et c'est possible pour plusieurs versions du même
objet dynamique d'exister dans le même répertoire. Ça ne sert
pas pour des objets systèmes, parce qu'ils dépendent du système,
et sont livrés avec le système, mais ça peut être utile dans le
cas des objets applicatifs.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|