簡體   English   中英

將向量從C ++ DLL調整到另一個C ++ EXE時出現問題

[英]Problem retuning a vector from a c++ dll to another c++ exe

我在dll A.dll中有一個函數foo(),其定義如下

vector<CustomObject> foo()  
{   
      vector<CustomObject> customObjectCollection;

   //code which populates customObjectCollection goes here

return customObjectCollection;   
}

我指的是exe B中dll A的此方法矢量foo()

當我從B調用函數foo時,出現未處理的異常,該異常表示

“ B.exe中0x10487b3f(msvcp90d.dll)處未處理的異常” 0xC0000005:寫入位置0xfdfdfdfd時訪問沖突。

注意:類型CustomObject不實現復制構造函數

當我嘗試通過將B.exe附加到A.dll進行調試時,我發現在方法vector foo()中,該向量的填充沒有任何問題,但是當控件返回到B.exe時,矢量中的閥不會被復制! !

另外,如果方法foo通過引用返回vector,則不會發生異常,並且B.exe收到一個空向量。

有什么問題? 是因為我沒有為CustomObject實現復制構造函數嗎?

非常感謝您的幫助(對於未能正確表達問題的道歉)

謝謝
je

這是運行時庫不匹配的典型症狀。 您必須確保EXE和DLL都鏈接到動態C ++庫(DLL版本)。

如果將一個(或兩個)都與靜態C ++運行時(LIB版本)鏈接,則將遇到內存沖突,因為將有兩個運行時庫實例具有不同的地址空間。

首先,您不應返回對在堆棧上聲明的本地對象的引用。 第二:對在STL容器中可以使用的元素有要求
1)復制構造函數
2)賦值運算符
3)公共破壞者
還有更多特定於容器的容器(例如關聯容器的分類標准)。
將創建復制構造函數以及賦值運算符(感謝編譯器),因此,除非您顯式隱藏它們-您的對象具有它們(如果您沒有復制構造函數,則編譯器會抱怨)。
但是這些隱式副本構造函數和賦值運算符可能不夠聰明,因此您可能想要實現自己的。 例如:假設您在構造函數中的CustomObject使用new創建了某個類的實例,並將其作為要在析構函數中銷毀的指針。 默認的復制構造函數將進行淺表復制,因此這將導致兩個對象持有相同的指針。 一旦其中一個被銷毀,第二個就會變得不一致(它持有已經釋放的指針)。

最后說明:盡量不要按值返回向量。 涉及大量復制。 在堆棧的調用方中聲明它,並將其作為對foo引用傳遞。

最安全的方法可能是:

bool foo(vector<someclass*> &customObjectCollection)
{
    //code which populates customObjectCollection goes here

    return success
}

通過這種方式,調用程序可以創建和維護向量,因此無需復制。 來電者會做

vector<someclass *> customObjectCollection;
foo(customObjectCollection);

另外,根據您的確切操作,請注意使用someclass指針的向量而不是someclass對象。

這里有很多可能性,您還沒有告訴我們足夠的信息來確定最有可能適用的方法。

一種可能性是(半)獨特的將代碼放入DLL。 如果您靜態鏈接標准庫,則每個模塊(EXE,DLL)都會獲得自己的內存管理,包括自己的堆,因此,很多嘗試在一個模塊與另一個模塊之間轉移內存所有權的操作都會因(貌似)奇怪而失敗。原因。 解決此類問題的方法通常是鏈接到DLL中所有模塊的標准庫。 這給出了在整個應用程序中共享的標准庫的一個副本,因此在模塊之間傳遞所有權不會造成問題。

另一種可能性是您的CustomObject類未正確處理復制。 由於您沒有告訴我們任何有關其內部的信息,因此我們無法猜測您可能需要在這里做什么。

暫無
暫無

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

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