Проблема перенастройки вектора из dll c ++ в другой exe c ++ - PullRequest
1 голос
/ 19 ноября 2009

У меня есть функция foo () в dll A.dll, определение которой выглядит следующим образом

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

   //code which populates customObjectCollection goes here

return customObjectCollection;   
}

Я имею в виду этот метод vector foo () из dll A из exe B

Когда я вызываю функцию foo из B, я получаю необработанное исключение, которое говорит

"необработанное исключение в 0x10487b3f (msvcp90d.dll) в B.exe " 0xC0000005: нарушение доступа при запись в адрес 0xfdfdfdfd ".

Примечание: тип CustomObject не реализует конструктор копирования

Когда я попытался отладить, подключив B.exe к A.dll, я обнаружил, что внутри метода vector foo () вектор заполняется без проблем, но когда элемент управления возвращается к B.exe, клапаны в векторе не получают скопировано !!!

Также, если метод foo возвращает вектор по ссылке, исключение не возникает и B.exe получает пустой вектор.

в чем проблема ?? Это происходит, поскольку я не реализовал конструктор копирования для CustomObject.

Любая помощь очень ценится (Извиняюсь за неправильное формулирование вопроса)

Спасибо
Jeel

Ответы [ 4 ]

4 голосов
/ 19 ноября 2009

Это классический признак несовпадающих библиотек времени выполнения. Вы должны убедиться, что и EXE, и DLL связаны с динамической библиотекой C ++ (версия DLL).

Если один (или оба) связаны со статической средой выполнения C ++ (версия LIB), вы получите нарушения памяти, так как будет два экземпляра библиотеки времени выполнения с разными адресными пространствами.

2 голосов
/ 19 ноября 2009

Прежде всего вы не должны возвращать ссылки на локальные объекты, объявленные в стеке. Второе: существуют требования к элементам, которые можно использовать в контейнерах STL
1) Копировать конструктор
2) Оператор присваивания
3) Публичный деструктор
Существует больше контейнеров (например, критерий сортировки для ассоциативных контейнеров).
Будет создан конструктор копирования, а также оператор присваивания (благодаря компилятору), поэтому, если вы явно не скрываете их - они есть у вашего объекта (если у вас не было конструктора копирования, компилятор будет жаловаться).
Но эти неявные конструкторы копирования и оператор присваивания могут быть недостаточно умными, поэтому вы можете захотеть реализовать свои собственные. Например: допустим, что ваш CustomObject в конструкторе создает экземпляр некоторого класса с new и сохраняет его как указатель, который будет уничтожен в деструкторе. Конструктор копирования по умолчанию создаст поверхностную копию, поэтому в результате два объекта будут содержать один и тот же указатель. Как только один из них уничтожен, второй становится несогласованным (он содержит указатель, который уже был освобожден).

Последнее замечание: старайтесь не возвращать вектор по значению. Много копирования связано. Объявите это в вызывающей программе в стеке и передайте как ссылку на вас foo.

1 голос
/ 19 ноября 2009

Здесь есть несколько возможностей, и вы недостаточно сообщили нам, чтобы определить, какие из них наиболее вероятны.

Одна возможность (полу) уникальна для помещения кода в DLL. Если вы статически связываете стандартную библиотеку, каждый модуль (EXE, DLL) получает свое собственное управление памятью, в том числе свою собственную кучу, поэтому довольно много операций, которые пытаются передать владение памятью между одним модулем и другим, завершатся (на первый взгляд) странно причины. Решение проблемы такого типа обычно заключается в создании ссылки на стандартную библиотеку в DLL для всех ваших модулей. Это дает одну копию стандартной библиотеки, общей для всего приложения, поэтому передача прав собственности между модулями не вызывает проблем.

Другая возможность состоит в том, что ваш класс CustomObject неправильно обрабатывает копирование. Поскольку вы ничего не сказали нам о его внутренностях, мы не можем угадать, что вам может понадобиться здесь.

1 голос
/ 19 ноября 2009

Вероятно, самый безопасный способ будет:

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

    return success
}

Таким образом, вызывающая программа создает и поддерживает вектор, поэтому нет необходимости копировать. Звонящий сделает

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

Кроме того, в зависимости от того, что именно вы делаете, обратите внимание на использование вектора указателей someclass, а не объектов someclass.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...