崩溃

2010-11-22 128 views
0

根据Using Rich Edit Controls我在这样的方式使用的RichEdit:崩溃

MyControl::OnCreate() 
{ 
    handle = LoadLibrary(_T("Riched20.dll")); 
} 

MyControl::OnDestroy() 
{ 
    FreeLibrary(handle); 
} 

它工作正常,为Win32,但页面重载之后最近我已经建立了64配置,现在我的控制失败。

alt text

我已经注意到,如果做到这一点:

MyControl::OnCreate() 
{ 
    handle = LoadLibrary(_T("Riched20.dll")); 
    FreeLibrary(handle); 
    handle = LoadLibrary(_T("Riched20.dll")); 
} 

一切工作正常。

我不希望将此代码投入生产,因此,有没有关于更好的解决方案/解决方法的建议?

回答

3

由于报告的故障模块是Richedit20.dll_unloaded,这意味着您正在卸载DLL,而其中的代码仍在使用中。

例如,如果在(完全)释放该DLL时仍然打开一个RichEdit窗口,只要有任何事件触发了该控件的window-proc调用就可以看到类似的崩溃。这是因为控件的window-proc在卸载的DLL代码中。

多次调用LoadLibrary和FreeLibrary应该是安全的(只要呼叫平衡),所以我怀疑这是问题所在。这可能只是触发问题。另外,问题出现在32位版本中;你很幸运,从来没有触发过它。

OnDestroy是调用FreeLibrary的错误地方。 WM_DESTROY(例如WM_NCDESTROY)后有几个窗口消息被发送到窗口。

当调用OnDestroy时,子窗口仍然存在。如果富有的人是你控制的孩子(而不是控制本身),那么将FreeLibrary移动到OnNcDestroy可能会节省你。 (子窗口在WM_NCDESTROY被调用时会被销毁)。但是,我仍然认为它不是释放库的好地方。

所以你一定要移动FreeLibrary调用。我会将它和LoadLibrary完全移出控件本身。每当创建它们的实例时,具有加载/释放库的控件是不正常的。相反,有一些静态的init/uninit代码会加载你需要的库,并在应用程序关闭时释放它们。 (如果你的应用程序很少使用控件,那么只有当使用控件的窗口处于活动状态时,才能加载/释放库是有意义的,但是这种情况很少发生,通常你最好离开DLL加载。)

+0

感谢您的快速回复。我已将代码移至DllMain,现在一切正常。再次感谢。 – Eugene 2010-11-22 06:59:22

+1

@Eugene乐意帮忙!顺便说一句,在DllMain中调用LoadLibrary也会导致问题。请参阅:http://blogs.msdn.com/b/larryosterman/archive/2004/04/23/118979.aspx - 理想情况下,您可以将此代码放入您的DLL的Init函数中,父应用程序在加载后调用它你的DLL。 (这也是注册控件的窗口类的正确位置。)但是,如果您无法控制父应用程序,那么事情会变得棘手。 :( – 2010-11-22 07:38:56