C++ boost::多索引容器与_com_ptr_t对象崩溃
我尝试将C++ boost::多索引容器与_com_ptr_t对象崩溃,c++,boost,C++,Boost,我尝试将boost::multi_index_container与\u com\u ptr\t对象一起使用。 代码编译时没有警告,但在运行时崩溃。 标准容器(std::set,map等)与此类对象完美配合 是否可以将多索引容器与com ptr一起使用 此处的示例代码: #include "stdafx.h" #include <boost\multi_index_container.hpp> #include <boost\multi_index\random_access_i
boost::multi_index_container
与\u com\u ptr\t对象一起使用。
代码编译时没有警告,但在运行时崩溃。
标准容器(std::set
,map
等)与此类对象完美配合
是否可以将多索引容器与com ptr一起使用
此处的示例代码:
#include "stdafx.h"
#include <boost\multi_index_container.hpp>
#include <boost\multi_index\random_access_index.hpp>
#include <boost\multi_index\global_fun.hpp>
#include <boost\multi_index\ordered_index.hpp>
#import "C:\Windows\SysWOW64\msxml6.dll" exclude("ISequentialStream", "_FILETIME")
using CTest =
boost::multi_index_container<MSXML2::IXMLDOMDocument2Ptr,
boost::multi_index::indexed_by<boost::multi_index::random_access<>>>;
int main()
{
::CoInitialize(nullptr);
CTest tst;
MSXML2::IXMLDOMDocumentPtr doc;
doc.CreateInstance(CLSID_DOMDocument);
tst.push_back(std::move(doc)); <-- crash here
::CoUninitialize();
return 0;
}
#包括“stdafx.h”
#包括
#包括
#包括
#包括
#导入“C:\Windows\SysWOW64\msxml6.dll”排除(“ISequentialStream”,“u FILETIME”)
使用CTest=
boost::多索引容器;
int main()
{
::共同初始化(nullptr);
CTest tst;
MSXML2::IXMLDOMDocumentPtr文档;
doc.CreateInstance(CLSID_DOMDocument);
tst.推回(std::move(doc));
- 我注意到您定义的
multi_index_容器
包含MSXML2::IXMLDOMDocument2Ptr
类型的指针,而doc
是MSXML2::IXMLDOMDocumentPtr
(没有2
)类型的指针。我假设这是可以的,因为问题实际上与这种差异无关
- Boost.MultiIndex,因此您可以随意使用
std::move
- 实际问题是,
\u com\u ptr\u t
有一个奇怪的、破坏性的返回指向包装接口的指针。这会混淆Boost.MultiIndex的内部代码。您可以通过如下方式轻松绕过此重载:
在没有std::move的情况下会发生崩溃吗(假设doc是可复制的)?在我看来,是boost::move导致了这个问题。“适当的检测”太模糊了,无法插入分支。所以不会。这是我单步执行代码时看到的。boost 1.55是的,我在没有std::move.tst.push_back(doc)的情况下会发生崩溃-另外,与操作符的死机链接&就像这是非常危险的一样,由于缺少IUnknown::Release()会导致内存泄漏call.看起来很奇怪,但编写它是为了期望程序员在查询接口调用中使用它,比如说,一种常见的编码模式。你是指我的修补还是\u com\u ptr\t
的修补?无论哪种方式,请注意用户定义的IXMLDOMDocument2Ptr
类仅在多索引容器中使用解决问题:应用程序的其余部分可以愉快地继续使用MSXML2::IXMLDOMDocumentPtr
。感谢您的解决方案。但我不能使用它。这只是一个示例。在实际代码中,我有很多这样的com接口包装。Ticket at添加了一种自动解决方案的方法,以防它对您有用。谢谢您的帮助。我ready编写了类似的解决方法,但我更喜欢boost::multi_index中的透明修复,因为它应该在许多开发人员的大型项目中使用。
#include <boost\multi_index_container.hpp>
#include <boost\multi_index\random_access_index.hpp>
#include <boost\multi_index\global_fun.hpp>
#include <boost\multi_index\ordered_index.hpp>
#import "C:\Windows\SysWOW64\msxml6.dll" exclude("ISequentialStream", "_FILETIME")
struct IXMLDOMDocument2Ptr:MSXML2::IXMLDOMDocument2Ptr
{
using MSXML2::IXMLDOMDocument2Ptr::IXMLDOMDocument2Ptr;
IXMLDOMDocument2Ptr* operator&(){return this;}
const IXMLDOMDocument2Ptr* operator&()const{return this;}
};
using CTest =
boost::multi_index_container<IXMLDOMDocument2Ptr,
boost::multi_index::indexed_by<boost::multi_index::random_access<>>>;
int main()
{
::CoInitialize(nullptr);
{
// defined in scope so that destruction happens before CoUninitialize
CTest tst;
MSXML2::IXMLDOMDocumentPtr doc;
doc.CreateInstance(CLSID_DOMDocument);
tst.push_back(std::move(doc));
}
::CoUninitialize();
return 0;
}
#include <boost\multi_index_container.hpp>
#include <boost\multi_index\random_access_index.hpp>
#include <boost\multi_index\global_fun.hpp>
#include <boost\multi_index\ordered_index.hpp>
#import "C:\Windows\SysWOW64\msxml6.dll" exclude("ISequentialStream", "_FILETIME")
template<typename CComPtr>
struct CFixedAddressofComPtr:CComPtr
{
using CComPtr::CComPtr;
CFixedAddressofComPtr* operator&(){return this;}
const CFixedAddressofComPtr* operator&()const{return this;}
};
template<typename CComPtr,typename TIndexList>
using CComPtrMultiIndexContainer=boost::multi_index_container<
CFixedAddressofComPtr<CComPtr>,
TIndexList
>;
using CTest =
CComPtrMultiIndexContainer<MSXML2::IXMLDOMDocument2Ptr,
boost::multi_index::indexed_by<boost::multi_index::random_access<>>>;
int main()
{
::CoInitialize(nullptr);
{
// declared in scope so that destruction happens before CoUninitialize.
CTest tst;
MSXML2::IXMLDOMDocumentPtr doc;
doc.CreateInstance(CLSID_DOMDocument);
tst.push_back(std::move(doc));
}
::CoUninitialize();
return 0;
}