Повреждение кучи при использовании кода DLL

У меня есть код, который мне нужно разместить в общей библиотеке dll. Этот код, класс CalibrationFileData, отлично работает, если он создан как часть текущего проекта. Однако, если CalibrationFileData собран в общей библиотеке, программа вылетает, указывая на повреждение кучи.

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

Что-то я пропустил?

Редактировать. Вот эти векторы:

std::vector<std::pair<CvPoint2D32f, CvPoint3D32f>>* extrinsicCorrespondences;
std::vector<int>* pointsPerImage;

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


person Kristian D'Amato    schedule 07.10.2011    source источник
comment
Меня беспокоит сам вектор. Поскольку это шаблон, DLL и EXE могут иметь разные экземпляры векторного кода. Возможно, это то, на что намекает trajanfoe — не уверен. Кроме того, вектор пар чего? Содержат ли пары указатели на объекты, размещенные в куче?   -  person Steve314    schedule 07.10.2011


Ответы (7)


Проверьте соответствие флагов компиляции между библиотекой и исполняемым файлом. Например, в Windows убедитесь, что вы используете одну и ту же библиотеку времени выполнения C (CRT) (/MD и /MT). Проверьте наличие предупреждений от компоновщика.

person Graham Perks    schedule 07.10.2011
comment
+1 Я поддерживаю это, особенно при использовании стандартной библиотеки шаблонов. - person Chris A.; 07.10.2011
comment
/MT недостаточно — он все равно создаст два экземпляра распределителя памяти. /MD (или /MDd) — это то, что вам нужно. - person Branko Dimitrijevic; 07.10.2011

Вы уверены, что когда вы берете на себя ответственность за содержимое объектов vector в своих методах, вы глубоко копируете их в свои переменные экземпляра?

person trojanfoe    schedule 07.10.2011

вы должны проверять глубокие копии внутри векторного объекта, я думаю, это относится к глубокому копированию

person Muhammed şahsuvaroğlu    schedule 07.10.2011

Могут ли быть разные значения, определенные для _SECURE_SCL в двух проектах?

person Jem    schedule 07.10.2011

Вероятно, вы пропустили какой-то фрагмент клиентского кода, который пытается освободить память, выделенную вашей DLL, или наоборот.

Возможно, проще всего было бы убедиться, что и клиент, и DLL используют один и тот же распределитель памяти. Не просто тот же вид, а тот же фактический «экземпляр» распределителя. В Visual C++ этого проще всего добиться с помощью как клиента, так и библиотеки DLL с помощью библиотеки времени выполнения "Многопоточная отладочная библиотека DLL (/MDd)" или "Многопоточная библиотека DLL (/MD)".

person Branko Dimitrijevic    schedule 07.10.2011

В параметре командной строки в Visual Studio удалите этот _SECURE_SCL. В основном этот сбой вызван несоответствием _SECURE_SCL среди деталей. Более подробную информацию можно найти здесь: http://kmdarshan.com/blog/?p=3830

person jusathr    schedule 10.10.2011

Следует различать сильно связанные и слабо связанные DLL.

Тесно связанные DLL означают, что

DLL построен с точно такой же версией компилятора, настройками упаковки и соглашения о вызовах, параметрами библиотеки, что и приложение, и оба динамически связаны с библиотекой времени выполнения (опция компилятора /MD). Это позволяет вам передавать объекты туда и обратно, включая STL контейнеры, выделять DLL объекты внутри приложения, наследовать от базовых классов в другом модуле, делать почти все, что вы могли бы делать без использования DLL. Недостатком является то, что вы больше не можете развернуть DLL независимо от основного приложения. Оба должны быть построены вместе. DLL предназначен только для улучшения времени запуска вашего процесса и рабочего набора, потому что приложение может начать работу до загрузки DLL (используя параметр компоновщика /delayload). Время сборки также меньше, чем для одного модуля, особенно когда используется оптимизация всей программы. Но оптимизация не происходит на границе между приложением и библиотекой DLL. И любое нетривиальное изменение все равно потребует перестройки обоих.

В случае слабо связанных DLLs, тогда

При экспорте функций DLL лучше всего, если они будут принимать только целочисленные типы данных, т. е. int или указатели.

Применительно, например, к строкам, тогда:

Когда вам нужно передать строку, передайте ее как const char *. Когда вам нужно, чтобы функция DLL возвращала строку, передайте в DLL указатель char * на предварительно выделенный буфер, куда DLL запишет строку.

Наконец, что касается распределения памяти, то:

Никогда не используйте память, выделенную DLL, вне собственных функций DLL, и никогда не проходите мимо структур значений, которые имеют собственный конструктор/деструктор.

Ссылки

Повреждение кучи при возврате из функции внутри dll

Могу ли я передать std::string в DLL?

person Vitality    schedule 17.07.2017