Связывание с библиотекой в ​​выпуске и .exe в случае отладки в Visual Studio - PullRequest
6 голосов
/ 04 августа 2009

Я использую Visual C ++ 2008 SP1. У меня есть приложение, скомпилированное в режиме отладки, но связанное с библиотекой в ​​режиме выпуска.

Я получаю сбой при запуске приложения. Чтобы уменьшить проблему, я создал простое решение с двумя проектами:

  • lib_release (генерирует .lib в режиме выпуска)
  • exec_using_lib_release (генерирует .exe в режиме отладки)

Проект 'lib_release' достаточно прост, чтобы иметь простой класс:

//Foo.h
#include <vector>
class Foo {
  std::vector<int> v;
  public:
  void doSomething();
};
//Foo.cpp
#include "Foo.h"
void Foo::doSomething() {}

Проект 'exec_using_lib_release' очень прост:

//main.cpp
#include "Foo.h"
int main() {
   Foo foo;
   foo.doSomething();
   return 0;
}

И он вылетает, это та же проблема, о которой сообщает Как создать отладочный .exe (MSVCRTD.lib) для библиотеки, выпущенной на основе релиза (MSVCRT.lib)? , но его ответ не помог работа для меня.

Я получаю те же предупреждения компоновщика, я пробовал те же шаги, но ни один не работал. Я что-то упускаю?

EDIT:

В lib_release (который создает библиотеку в режиме выпуска) я использую Multi-Threading (/ MT) , а в exec_using_lib_release я использую Multi-Threading Debug (/ MTd) . Я думаю, что это ожидаемый способ сделать это, так как я хочу, чтобы .lib создавался без отладочной информации. Я прочитал документ в MSDN Runtime library , и это настройки статического связывания с CRT.

У меня нет «Общей поддержки времени исполнения».

Ответы [ 4 ]

8 голосов
/ 04 августа 2009

У вас нет , чтобы использовать одни и те же среды выполнения для модулей выпуска и отладки (но это помогает), если вы следуете очень специфическим правилам: никогда не смешивайте и не сопоставляйте доступ к памяти, выделенной с помощью каждого во время выполнения.

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

Если вы считаете, что библиотеки Windows построены только на выпуск (если у вас нет отладочной версии Windows), но вы используете их из своих приложений отладки, вы увидите, как это важно.

Ваша проблема сейчас в том, что вы используете статическую библиотеку, границы dll больше нет, а вызовы в библиотеке компилируются с использованием статической версии среды выполнения C. Если ваш exe использует динамическую dll-версию среды выполнения, вы обнаружите, что компоновщик использует ее вместо той, что использовала ваша статическая библиотека ... и вы получите сбои.

Итак, вы можете перестроить свою библиотеку как dll; или вы можете убедиться, что они оба используют одну и ту же библиотеку CRT; или вы можете убедиться, что они оба используют один и тот же тип CRT - то есть версию dll или статическую версию, сохраняя при этом различия отладки / выпуска.

По крайней мере, я думаю, что это ваша проблема - каковы настройки «Генерация кода, библиотека времени выполнения»?

5 голосов
/ 04 августа 2009

В случае сочетания проблем с выпуском и отладкой, о которых упоминали ранее, эти проблемы не будут отображаться до тех пор, пока неправильная библиотека времени выполнения не попытается отменить выделение. Я думаю, что вы сталкиваетесь с тем, что в VS 2008 включена отладка итераторов по умолчанию, поэтому ваша библиотека и исполняемый файл ссылаются на разные реализации std :: vector. Вы захотите добавить _HAS_ITERATOR_DEBUGGING = 0 в настройки препроцессора. Затем вы начнете решать проблему разных куч для разных сред выполнения. В прошлом у нас были разные правила и политики, чтобы этого избежать, но теперь мы просто полагаемся на согласованную среду сборки - не смешивайте и не сопоставляйте.

2 голосов
/ 04 августа 2009

Проблема здесь в том, что для отладки будет использоваться отладочная версия среды выполнения c, а в выпуске будет использоваться версия выпуска среды выполнения c, и когда вы попытаетесь получить доступ к памяти через границу dll, это будет в неправильном времени выполнения и сбой. Все способы лучше всего использовать только отладочные сборки (или выпустить)

0 голосов
/ 22 августа 2017

Присоединенная библиотека не должна совместно использовать ресурсы ЭЛТ через границы библиотеки. Для кода C динамически выделенная память должна быть освобождена на той же стороне границы. Для кода C ++ вы можете использовать пространство имен std внутри вашей DLL, но эти объекты, использующие пространство имен std, должны передаваться через границы библиотеки.

см. этот ответ на аналогичный вопрос

...