J'ai écrit quelque chose pour charger des fichiers PNG à partir d'un IStream C++ personnalisé via GDI +. Cela a fonctionné très bien jusqu'à ce que je l'ai couru sur des machines de Vista. Crashes à chaque fois.GDI + se bloque lors du chargement PNG à partir de IStream
Lors de la compilation sur VS 2008, j'ai trouvé que l'insertion de code dans la méthode IStream::AddRef
, comme un cout
, a fait disparaître le problème. Lors de la compilation avec VS 2010, il se bloque toujours indépendamment de cela. J'ai dépouillé le programme de ses principes de base. J'ai copié un FileStream directement à partir de la documentation de Microsoft. Il peut charger des fichiers PNG en utilisant Bitmap::FromFile
. Il peut charger des fichiers JPEG, GIF et BMP via FromFile
ou FromStream
. Donc, en bref: sur Vista, les fichiers PNG chargés par Bitmap::FromStream
crash. Le suivi et le débogage montrent qu'il effectue certains appels à la classe IStream. Il se bloque à l'intérieur de lastResult = DllExports::GdipCreateBitmapFromStream(stream, &bitmap);
de GdiPlusBitmap.h
, qui est un encapsuleur statique en ligne sur l'API plat.
Outre le comptage de références, les seules méthodes IStream appelées sont stat
(pour la taille de fichier), read
et seek
.
pile d'appel ressemble à:
- [email protected]() + 0x1 octets
- [email protected]() + 0x28 octets
- ntdll.dll _RtlpValidateHeapEntry @ 12() + 0x70a3c octets
- [email protected]() + 0x9A octets
- ntdll.dll! @ RtlpFreeHeap @ 16() + 0x13cdd octets
- ntdll.dll! _RtlF reeHeap @ 12() + 0x2e49 octets
- [email protected]() + 0x14 octets
- ole32.dll! CRetailMalloc_Free() + 0x1c octets
- [email protected]() + 0x13 octets
- GdiPlus.dll! GpPngDecoder :: GetImageInfo() + 0x68 octets
- GdiPlus.dll! GpDecodedImage :: InternalGetImageInfo() + 0x3c octets
- GdiPlus.dll! GpDecodedImage :: GetImageInfo() + 0x18 octets
- GdiPlus.dll! CopyOnWriteBitmap :: CopyOnWriteBitmap() + 0x49 octets
- GdiPlus.dll! CopyOnWriteBitmap :: Créer() + 0x1D octets
- GdiPlus.dll! GpBitmap :: GpBitmap() + 0x2c octets
Je ne pouvais pas trouver quelqu'un d'autre avec le même problème, donc je suppose qu'il y a quelque chose qui ne va pas avec mon implémentation ...
Je ne peux pas non plus reproduire sur Win7. Cela n'arrive que sur Vista. Le code ci-dessus est tout ce qui est nécessaire pour planter. Mon vrai projet définit réellement la structure 'stat'. Cependant ... je pense que vous avez raison. Le coupable ressemble à 'pwcsName'. Dans mon code de projet réel, je ne définis pas ce champ lors du chargement de l'image car Microsoft passe le champ 'STATFLAG_NONAME', ce qui signifie qu'ils ne veulent pas le nom. Cependant, il semble qu'ils utilisent encore le nom sur le chargement PNG si 'pwcsName' est non nul. Je suppose qu'ils ont quelque chose comme 'if (s-> pwcsName) libre (s-> pwcsName)', au moins sur la bibliothèque Vista GDI. – Matthew
En réglant le pointeur 'pwcsName' sur des valeurs non-debug, j'en suis arrivé à la conclusion qu'il y a un comportement différent dans Vista et dans la bibliothèque GDI + de Windows 7 (ou quelque chose d'associé). Windows 7 ne le libérera jamais s'il passe 'STATFLAG_NONAME', mais Vista le fera toujours. Le définir sur 'NULL' quand' STATFLAG_NONAME' est réglé corrige le problème. – Matthew