为什么会出现此错误?引用计数增加,线程模型是单个公寓。 Coll-object和EmptyColl函数都位于一个dll中。 ATL项目的默认调用转换是__stdcall。与此dll中的其他对象发生相同的错误。
当使用NULL-object清除VARIANT时,VariantClear会抛出异常:
在VB6.EXE中0x75C14974(oleaut32.dll)抛出异常:0xC0000005:
访问冲突读取位置0x00000008。
frmMain.frm(错误,见下文原因):
Private Sub Form_Load()
Dim c As Coll
Set c = EmptyColl
'error when ends here with variable "c" in the watch window.
End Sub
frmMain.frm(没有错误):
Private Sub Form_Load()
Dim c2 As Coll 'instead of Coll can be any object of same library
Set c2 = New Coll 'creation
Set c2 = Nothing 'destroying (optionaly)
Dim c As Coll
Set c = EmptyColl
'no error
End Sub
filyus.idl:
[
object,
uuid(6FA7FAEB-5CE3-4A80-9288-2667EE5E7596),
dual,
nonextensible,
pointer_default(unique)
]
interface IColl : IDispatch{
//some methods
};
[
uuid(157F3D2F-A427-4D5A-B908-87868297EA43),
version(1.0),
]
library Filyus
{
importlib("stdole2.tlb");
[
dllname("Filyus")
]
module Filyus{
[entry("EmptyColl")]
HRESULT EmptyColl([out, retval] IColl** Coll);
}
};
filyus.def:
LIBRARY
EXPORTS
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
DllInstall PRIVATE
EmptyColl
ole.h:
extern HRESULT EmptyColl(IColl** Coll);
ole.cpp:
HRESULT EmptyColl(IColl** Coll) {
HRESULT hr; CComObject<CColl>* Object;
if (Coll != nullptr) {
hr = CComObject<CColl>::CreateInstance(&Object);
if (hr == S_OK) {
Object->AddRef();
*Coll = Object; //same error with using QueryInterface
}
}
else hr = E_POINTER;
return hr;
}
答案 0 :(得分:0)
EmptyColl()
需要使用__stdcall
调用约定:
extern HRESULT __stdcall EmptyColl(IColl** Coll);
HRESULT __stdcall EmptyColl(IColl** Coll) {
//...
}
或者,使用STDMETHODCALLTYPE
宏,该宏解析为__stdcall
:
extern HRESULT STDMETHODCALLTYPE EmptyColl(IColl** Coll);
HRESULT STDMETHODCALLTYPE EmptyColl(IColl** Coll) {
//...
}
如果没有声明调用约定,默认情况下,C / C ++编译器将使用__cdecl
,除非配置不同。 __cdecl
和__stdcall
以不同方式管理调用堆栈。如果不使用正确的调用约定,则会损坏调用堆栈。 COM标准需要__stdcall
,这就是VB所期望的。
答案 1 :(得分:0)
由于对对象的错误访问而发生错误
CComPtr用于客户端,CComObject用于服务器端(直接访问,只有在您已经创建了该库的任何对象时才获取它)。
正确的ole.cpp:
HRESULT EmptyColl(IColl** Coll) {
HRESULT hr; CComPtr<IColl> Object;
if (Coll != nullptr) {
hr = Object.CoCreateInstance(CLSID_Coll);
if (hr == S_OK) {
Object.CopyTo(Coll);
}
}
else hr = E_POINTER;
return hr;
}