我今天在我的代码中遇到了一个问题,即通过将我的COM对象转换为IUnknown**来导致访问冲突,AFAICT.传递给它的函数没有问题但是当调用我的一个对象的函数时,它会执行一些随机函数并破坏堆栈然后死掉.
指示性代码(只是忽略它为什么这样做 - 我知道它很糟糕,我知道如何修复它但这是一个问题,为什么会出现这样的问题):
void MyClass2::func(IMyInterface* pMyObj)
{
CComPtr<IMyInterface2> pMyObj2;
HRESULT hRes = pMyObj->GetInternalObject((IUnknown**)&pMyObj2);
if (SUCCEEDED(hRes))
pMyObj2->Function(); // corrupt stack
}
void MyClass::GetInternalObject(IUnknown** lpUnknown)
{
pInternalObject->QueryInterface(IID_IMyInterface2, (void**)lpUnknown);
}
Run Code Online (Sandbox Code Playgroud)
我一直有点怀疑在COM对象上使用C/C++强制转换但我从未遇到(可能通过未定义的行为)直到现在的任何问题.
我快速浏览了一下,从我可以告诉我的转换到IUnknown在技术上是有效的,只要在继承链中没有多重干扰,但它不被认为是最佳实践 - 我应该将IUnknown传递给MyClass::GetInternalObject(IUnknown** lpUnknown)然后查询返回我想要的接口的价值.
我的问题是,是否存在关于何时可以在COM对象上使用C/C++强制转换的规则,除了多重继承和它们带来的调整器thunks之外,如何转换COM对象会导致诸如访问冲突之类的惊喜?请详细说明.
编辑:他们都是应该如何正确完成的好例子,但我希望的是技术解释为什么你不应该强制转换COM对象(假设存在一个),例如,在情境x中,施法会返回pMyObj2-4 但是QueryInterface将返回pMyObj2-8因为y ...或者仅仅是一个糟糕的练习/风格的COM对象?
TIA
我有一些函数用于将2D变体SAFEARRAY转换为各种STL容器,有点像(仅限说明)
template<typename T>
std::set<T> SetFromSafeArray(VARIANT srcArray)
{
CComSafeArray<T> srcComArray(srcArray.parray);
std::set<T> destContainer;
for (ULONG i=0;i<srcComArray.GetCount();++i)
destContainer.insert(srcComArray.GetAt(i));
return destContainer;
}
Run Code Online (Sandbox Code Playgroud)
我觉得这不是一个非常简单的方法,它意味着我转换为每个STL容器都有一个单独的功能.
我的想法是为CComSafeArrays编写一个包装器和自定义迭代器,所以我可以做...
std::copy(srcComArray.begin(), srcComArray.end(), destContainer.begin());
Run Code Online (Sandbox Code Playgroud)
但是之前从未写过迭代器并且是新手我真的不知道它是否容易.
自定义CComSafeArray迭代器是我最好的,标准的c ++之类的选项(在这种情况下,我确信我可以找到一个关于编写迭代器的好教程)?还是有其他方法可以解决这个问题吗?
Boost不是一个选择.
TIA
我正在尝试从WER在崩溃时采用的本机转储中提取Java堆转储:
jstack -m -l "c:\Program Files\Java\jre6\bin\java.exe" WER.tmp.hdmp
Run Code Online (Sandbox Code Playgroud)
但我得到以下异常:
Attaching to core c:\Users\xxx\Desktop\WER.tmp.hdmp from executable c:\Program Files\Java\jre6\bin\java.exe, please wait...
sun.jvm.hotspot.debugger.NoSuchSymbolException: Could not find symbol "gHotSpotVMTypes" in any of the known library names (jvm.dll, jvm_g.dll)
at sun.jvm.hotspot.HotSpotTypeDataBase.lookupInProcess(HotSpotTypeDataBase.java:389)
at sun.jvm.hotspot.HotSpotTypeDataBase.readVMTypes(HotSpotTypeDataBase.java:104)
at sun.jvm.hotspot.HotSpotTypeDataBase.<init>(HotSpotTypeDataBase.java:85)
at sun.jvm.hotspot.bugspot.BugSpotAgent.setupVM(BugSpotAgent.java:565)
at sun.jvm.hotspot.bugspot.BugSpotAgent.go(BugSpotAgent.java:494)
at sun.jvm.hotspot.bugspot.BugSpotAgent.attach(BugSpotAgent.java:348)
at sun.jvm.hotspot.tools.Tool.start(Tool.java:169)
at sun.jvm.hotspot.tools.JStack.main(JStack.java:86)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at sun.tools.jstack.JStack.runJStackTool(JStack.java:118)
at sun.tools.jstack.JStack.main(JStack.java:84)
Debugger attached successfully.
jstack requires a java VM process/core!
Run Code Online (Sandbox Code Playgroud)
我仔细检查过:
如果我尝试使用jmap提取java堆转储,我会得到完全相同的错误.
有谁知道会出现什么问题?
c++ ×2
atl ×1
casting ×1
com ×1
containers ×1
crash-dumps ×1
java ×1
jmap ×1
jstack ×1
variant ×1