C++编译器XE5:初始化GDI+时发生访问冲突

C++ Builder XE5: access violation on initialization of GDI+

本文关键字:访问冲突 GDI+ 初始化 编译器 XE5 C++      更新时间:2023-10-16

我正在Embarcadero XE5(C++Builder)中用表单编写简单的应用程序。它使用GDI+1.1。在存在函数(底部列出的代码)的情况下,应用程序在初始化(或取消初始化)GDI+时会因访问冲突而退出。原因是什么?

代码:

#pragma hdrstop
#pragma argsused
#define GDIPVER 0x0110
#include <windows.h>
#include <gdiplus.h>
using namespace Gdiplus;
extern "C"
{
  long int ConvertToPng8File(void* image)
  {
    Gdiplus::Bitmap* newimage = (Gdiplus::Bitmap*)image;
    ColorPalette* pal = (ColorPalette*)malloc(sizeof(ColorPalette) + 255*sizeof(ARGB));
    pal->Count = 256;
    pal->Flags = 0;
    Gdiplus::Bitmap::InitializePalette(pal, PaletteTypeOptimal, 256, false, newimage);
    newimage->ConvertFormat(PixelFormat8bppIndexed, DitherTypeSolid, PaletteTypeOptimal,pal,0);
    free(pal);
  }
}

堆栈:

:0000000077b9e4b4
:0000000077B9E3DB ; ntdll.dll
:000007FEFBFE9EE1 ; C:WindowsWinSxSamd64_microsoft.windows.gdiplus_6595b64144ccf1df_1.1.7601.17514_none_2b24536c71ed437aGDIPLUS.DLL
:0000000009af156f ; Winapi::Gdipobj::initialization()
:0000000009bdacb6 ; _init_exit_proc
:0000000009bdaf70 ; _wstartupd
:00000000098f23b6 ; __acrtused

消息:

First chance exception at $0000000077B9E4B4. 
Exception class $C0000005 with message 'c0000005ACCESS_VIOLATION'.
Process ImageryCreator64.exe (5648)

堆栈跟踪显示错误发生在程序的启动序列期间,甚至在调用main之前,即在初始化某些非本地静态GDI对象期间。

很明显,您正在尝试初始化静态GDI对象,但在静态初始化过程中,您无法保证初始化顺序,甚至无法保证所需的库是否已经加载和初始化:这是经典的静态初始化顺序惨败。

您需要在程序序列的后面移动基于GDI的对象的初始化:要么在main调用的某个初始化函数中,要么在singleton中。