0

我有这个功能,

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)。(生成带有lib的DLL)在其他一些项目中我使用这个函数如下,

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

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

为什么会这样?怎么了?为什么它在调试模式下工作?

- 编辑 -

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..
}

-- 编辑:结论 --

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

4

2 回答 2

1

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

于 2013-01-18T20:41:59.147 回答
1

另一种理论:

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

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

于 2013-01-18T21:22:19.610 回答