Std::vector在返回之前被自动清除

std::vector is cleared automatically before returning it

本文关键字:清除 vector 返回 Std      更新时间:2023-10-16

我有这个函数,

vector<QDC::AdapterUserInfo> QDC::QueryInterface::RetrieveAdapterList()
{
    vector<QDC::AdapterUserInfo> retVal;
    InnerQueryInterface::IISTATE::Transition trans = _IQI->AdapterList(retVal);
    if (trans._OldState == trans._NewState)
    {
        if ( trans._NewState != InnerQueryInterface::IISTATE(trans._OldState).SuccessfulTransition(trans._Transition) )
        {
            throw Exceptions::FunctionFailed();
        }
    }
    return retVal;
}

QDC是一个命名空间。QueryInterface是由__declspec(dllexport)导出的一个类。(生成带有库的DLL)在其他一些项目中,我像下面这样使用这个函数:

vector<QDC::AdapterUserInfo> aui = Qui.RetrieveAdapterList();

但是在Release版本中vector总是返回大小为0的值。但是返回大小为1(这是元素的实际数目)。我在发布模式下调试,发现RetrieveAdapterList函数里面的retVal填充了实际的数据,然后在函数的最后一行,也就是return retVal;行,显示retVal向量为cleared变为空。因此,最后返回的值是一个空向量。

为什么会发生这种情况?怎么了?为什么它在调试模式下工作?

——编辑——

在继续执行到其作用域结束后,vector对象aui的析构函数似乎失败了。

——调用者代码——

void DXE::Screen::Initialize( const HWND in_Window, const bool in_Windowed )
{
    QDC::UsableParameters UP;
    QDC::QueryInterface Qui;
    vector<QDC::AdapterUserInfo> aui = Qui.RetrieveAdapterList();
    if( aui.size() <= 0 )
    {
        throw Exceptions::UnknownException();
    }
    Qui.SelectAdapter(0);
    Qui.SelectDisplayMode(in_Windowed);
    UP = Qui.RetrieveParameters();
    _AdapterOrdinal = UP._AdapterOrdinal;
    _D3DPresentParams.BackBufferWidth = UP._Width;
_D3DPresentParams.BackBufferHeight = UP._Height;
_D3DPresentParams.BackBufferFormat = UP._BackBufferFormat;
    //..... fills the _D3DPresentParams..
}

—EDIT: Conclusion—

在多次尝试之后,出现了一个错误消息,说可能发生了堆崩溃,这就是Peter Ruderman提出的原因。所以我从使用动态库改为静态库,这样堆的东西可能不会发生在这种情况下(至少这是我的想法)。然后程序似乎运行得很好,没有任何问题。所以结论应该是彼得的理论是正确的。谢谢大家的帮助。

另一个理论:

"QDC是一个命名空间。QueryInterface是一个使用__declspec(dllexport)导出的类。(生成带有库的DLL)"

如果我理解正确,你说功能Screen::Initialize驻留在您的可执行模块中,但功能QueryInterface::RetrieveAdapters列表驻留在DLL中。在这种情况下,DLL分配内存,然后移动到调用站点。当aui超出作用域时,您的exe将删除内存。如果DLL和exe使用不同的堆,这可能会导致严重的错误(堆损坏)。

这不是您的bug的根源。在VS2010使用的c++ 11的早期版本中,向量是不可构造的。在return语句中,局部变量retval变为右值,因此编译器将其内容移到调用站点的"aui"变量中。(实际上,它只是交换了aui和retrieve的内容。)如果您也跟踪调试构建,您应该会看到这种行为。