簡體   English   中英

發布模式與MS Visual Studio Windows中的DEbug模式相同

[英]Release mode Vs DEbug mode in MS Visual Studio Windows

我正在使用MSVS 9(VS 2008)。 我的應用程序以及共享庫(dll)(我用來鏈接我的應用程序)也是c ++環境。 現在觀察以下情況:

  1. 在調試模式下構建共享庫/ dll時,我的應用程序也在調試模式下構建結果:應用程序已成功執行

  2. 在發布模式下構建共享庫/ dll時,我的應用程序也在發布模式下構建結果:應用程序已成功執行

  3. 當共享庫/ dll在發布模式下構建並且我的應用程序也在調試模式下構建時結果:應用程序崩潰而不從調用堆棧加載任何符號。

    調用堆棧:

    ntdll.dll中!76e94684()
    [下面的框架可能不正確和/或缺失,沒有為ntdll.dll加載符號]

    ntdll.dll中!76e7d55f()
    ntdll.dll中!76e5fa18()
    ntdll.dll中!76e2b3c8()

當我嘗試在我的應用程序中使用以下SetName()和GetName()定義時,會出現此問題。

    using namespace std;
    void main()
    { 
        Schema * schemaExp = new Schema();
        schemaExp -> SetName("ExpSchema");
        string srctable;
        srctable=schemaExp->GetName();
        cout <<"\nConnection EXPORT using the target table:" << srctable.c_str()  << endl;
        delete schemaExp;
    }

架構類定義:

    using namespace std;
    class Schema
    {
       public:
       TELAPI_EXPORT void   SetName(char *name); 
       TELAPI_EXPORT string     GetName(); 
      protected: 
       string tableName; 
    };
    void Schema::SetName(char *name)
    { 
       string str(name);
       tableName = str; 
    }
    string Schema::GetName()
    {
      return tableName;
    }

注意:上面的一個只是我的應用程序的一部分,我的應用程序只在#3中崩潰,並且在上面的#1和#2情況下正常工作

請幫我解決這個問題。 非常感謝任何形式的幫助。

提前致謝。

當共享庫/ dll在發布模式下構建並且我的應用程序也在調試模式下構建時結果:應用程序崩潰而不從調用堆棧加載任何符號。

那是因為這不是受支持的配置。 默認情況下,調試和發布目標鏈接到CRT的不同版本,其中(除其他外)使用不同的策略來分配內存並且彼此不兼容。

這只是更一般規則的擴展,您不應該混合鏈接到不同版本的CRT的庫。 所有項目都需要匹配。 正如你已經看到的,當他們這樣做時,一切正常。

有這方面的解決方法,但他們需要做很多工作才能做對。 實質上,您確保在單個DLL中隔離所有內存分配,以便不會跨越模塊邊界。 您需要從DLL中導出特定的函數來分配和釋放內存,以確保分配內存的堆管理器與銷毀內存的堆管理器相同。 使用newdelete運算符時,不能依賴於這種情況。 坦率地說,在這種情況下,我看不出所有這些努力如何為你帶來任何有用的東西。

請注意,這與是否啟用了優化無關(默認情況下,它們是發布版本,並且不在調試版本中)。 該設置與鏈接的CRT版本正交。恰好“Debug”和“Release”目標意味着多個選項。 您可以打開一個項目的優化並將其關閉另一個項目,這應該有效,只要您確保它們都鏈接到相同版本的CRT。 但同樣,我真的沒有看到這樣做的重點...如果你想為一個啟用優化,為什么你希望它們被另一個抑制?

相關: 混合調試和發布庫/二進制 - 不好的做法?

這不應該是崩潰,但是,通常你會在Windows內存管理器中得到一個調試中斷,以警告你程序正在破壞堆。 Windows中調試堆的一個功能,可在Vista及更高版本上使用。 在“輸出”窗口中查找消息。

啟用符號服務器也很重要,這樣堆棧跟蹤就變得可讀和准確。 使用工具+選項,調試,符號並勾選預定義的msdl.microsoft.com服務器名稱前面的復選框。 為符號存儲選擇一個好的臨時目錄。 當您再次啟動程序時,它將在開始運行之前暫停一段時間,下載符號文件。 這只發生過一次。 您現在應該獲得高度可讀的堆棧跟蹤,現在也可以返回到main()方法。

您通常發現的是,跨模塊邊界公開C ++類是一件棘手的事情。 不止一件事可能出錯,這里的一種失敗模式是Schema類對象在DLL邊界兩側的大小不同。 這是因為Debug構建設置, _HAS_ITERATOR_DEBUGGING #define很重要。 它在Debug版本中默認打開,在Release版本中關閉。 很好的調試功能,但他們實現它的唯一方法是向標准C ++庫類添加字段。 這使得std :: string在Debug版本中更大。 這使您的Scheme類更大。 您現在正在避開此問題,失敗模式是具有EXE版本的DLL的調試版本。 然后,Scheme類構造函數在初始化字符串時會破壞堆,因為對象的分配不夠大。

另一種失敗模式是您的流程中有兩個版本的CRT,應用程序中的調試版本以及DLL中的發行版本。 他們不會使用相同的堆來分配。 當你在一個中分配並在另一個中釋放時會出錯。 GetName()方法返回的字符串會遇到該問題,它是在DLL內部的GetName()方法中創建的,並且在EXE中調用方法后將被銷毀。 由錯誤的分配器。 在您再次對堆執行某些操作(例如刪除Scheme對象)之前,不會檢測到導致這種堆的損壞。 如果不使用/ MD構建代碼,也可以調用此故障模式。 在VS2012 btw中解決了這個問題,所有分配現在都來自默認進程堆。

使用一致的構建設置對於在模塊邊界中生存至關重要。 設置VS解決方案以便始終始終如一地使用DLL的正確構建不是問題,只需確保DLL項目與EXE項目在同一解決方案中。

但請注意,將來你可能會遇到麻煩,DLL有自己的生活訣竅,並且可能有一天會被另一個版本的編譯器構建的應用程序使用。 Kaboom然后。 設計你的DLL接口以便永遠不會發生這種情況,但你必須放棄暴露C ++對象。 C風格的界面是后備,COM將其提升為對象模型的方式也是一種很好的方法。 當然,這非常嚴苛,如果你不能保證EXE和DLL總是同時構建和部署,那么只考慮這個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM