24 5月 2013

[C/C++] 使用STL時,混用Debug & Release Mode的DLL or LIB可能會造成 Crash!

當你的Release mode的EXE,使用Debug mode的DLL,中間如果有操作(new/delete)STL的container,很容易讓AP crash,包括下列的error ...
  • Debug Assertion Failed
  • _BLOCK_TYPE_IS_VALID
  • _CrtIsValidHeapPointer



主要是因為build Debug mode的DLL,STL會enable _SECURE_SEL 和 _HAS_ITERATOR_DEBUGGING,裡面會對memory多做一些checking,假如你在Release mode,new了一塊memory後放到Debug mode的STL container,在Debug mode裡試著去delete這塊memory時,會多做一些Release mode不會做的error checking,就會有不預期的exception出現。

想想,Release跟Debug所用的CRunTime library是不一樣的,同一塊memory讓不一樣的CRunTime處理,當然可能會出錯。

解決辦法:
  • (不混用) 將全部的module統一build成Release or Debug mode
  • (大統一) Memory allocated/free的行為,統一交給一個module處理

Sample Error Code :
////////////////////////////////////////////////////////
// A.dll - build in Release mode
////////////////////////////////////////////////////////
B bMgr;
void AppendIntArray(int* array, int size)
{
    for(int i=0 ; i<size ; ++i)
    {
        // New memeory in A.dll (Release Mode)
        bMgr.m_int.push_back(new Value<int>(array[i])); 
    }
}
void AppendFloatArray(float* array, int size)
{
    for(int i=0 ; i<size ; ++i)
    {
        // New memeory in A.dll (Release Mode)
        bMgr.m_float.push_back(new Value<float>(array[i]));
    }
}


////////////////////////////////////////////////////////
// B.dll - build in Debug mode
////////////////////////////////////////////////////////
template <typename T>
class Value
{
public:
    Value(T _v){v=_v;}
    T v;
}

class B
{
public:
    void ClearAll();
    vector< Value<int>* > m_int;
    vector< Value<float>* > m_float;
}

void B::ClearAll()
{
    // Release memeory in B.dll (Debug Mode)
    for(int i=0 ; i<m_int.size() ; ++i)
        delete m_int[i];
    m_int.clear();
    
    // Release memeory in B.dll (Debug Mode)
    for(int i=0 ; i<m_float.size() ; ++i)
        delete m_float[i];
    m_float.clear();
}



Reference 

沒有留言: