【发布时间】:2013-12-16 15:01:30
【问题描述】:
在 D 中,每次启动应用程序时,我的垃圾收集器都会崩溃。
Windows 模块:
pragma(lib, "user32.lib");
import std.string;
extern(Windows) {
void* CreateWindowExW(uint extendedStyle ,
const char* classname,
const char* title,
uint style,
int x, int y,
int width, int height,
void* parentHandle,
void* menuHandle,
void* moduleInstance,
void* lParam);
}
class Window {
private void* handle;
private string title;
this(string title, const int x, const int y, const int width, const int height) {
this.title = title;
handle = CreateWindowExW(0, null, toStringz(this.title), 0, x, y, width, height, null, null, null, null);
if(handle == null)
throw new Exception("Error while creating Window (WinAPI)");
}
}
主模块:
import std.stdio;
version(Windows) {
import windows;
extern (Windows) {
int WinMain(void* hInstance, void* hPrevInstance, char* lpCmdLine, int nCmdShow) {
import core.runtime;
Runtime.initialize();
scope(exit) Runtime.terminate();
auto window = new Window("Hello", 0, 0, 0, 0);
writeln("test");
return 0;
}
}
}
这给了我位置 0 的访问冲突。当我查看反汇编时,它崩溃了
0040986F mov ecx,dword ptr [eax]
此程序集位于_gc_malloc 内。
编辑:这是新代码:
Windows 模块:
pragma(lib, "user32.lib");
import std.utf;
extern(Windows) {
void* CreateWindowExW(uint extendedStyle ,
const wchar* classname,
const wchar* title,
uint style,
int x, int y,
int width, int height,
void* parentHandle,
void* menuHandle,
void* moduleInstance,
void* lParam);
}
class Window {
private void* handle;
private wstring title;
this(wstring title, const int x, const int y, const int width, const int height) {
this.title = title;
handle = CreateWindowExW(0, null, toUTFz!(wchar*)(this.title), 0, x, y, width, height, null, null, null, null);
if(handle == null)
throw new Exception("Error while creating Window (WinAPI)");
}
}
WinMain:
int WinMain(void* hInstance, void* hPrevInstance, char* lpCmdLine, int nCmdShow) {
import core.runtime;
try {
Runtime.initialize();
scope(exit) Runtime.terminate();
auto window = new Window("Hello", 0, 0, 0, 0);
writeln("test");
} catch(Exception ex) {
writeln(ex.toString);
}
return 0;
}
当我运行第二个代码时,我还会在随机(对我而言)地址上遇到访问冲突。
拆解(在__d_createTrace内):
0040C665 cmp dword ptr [ecx+1Ch],0
【问题讨论】:
-
Runtime.initialize 和范围 exit runtime.terminate 都应该在 outside 尝试中,将它们放在函数的最顶部,然后尝试您的代码。现在发生的事情是新窗口抛出异常(就像大卫所说,你需要先注册一个窗口类而不是传递 null),然后在尝试结束时,运行时终止。所以在 catch 内部,这些东西没有设置好,toString 调用无法完成它的工作。所以移动上面的那两条运行时行,你应该会得到一个很好的异常消息框。
标签: winapi memory-management garbage-collection d