Проблема столкновения библиотек VC ++ - PullRequest
2 голосов
/ 10 января 2010

Я работаю над проектом C ++, который использует Qt (gui lib), VTK (graphics lib) и другую библиотеку, которая настолько неясна, что я не буду называть ее имя и вместо этого назову ее LIB_X. Проект использует Qt для компонентов графического интерфейса и VTK (точнее, расширение QVTKWidget, предоставляемое VTK, которое поддерживает Qt) для рендеринга геометрии ... и использует LIB_X для сбора и манипулирования геометрией.

Проблема в том, что LIB_X действительно использует VTK (где и как, я не знаю, это закрытый источник). Сначала проблем не было, компиляция с обеими связанными библиотеками проходила нормально, но в какой-то момент я вызвал определенную (и крайне необходимую) функцию LIB_X, и компиляция привела к куче «бла-бла-то» об уже определенном lib / obj VTK в LIB_X dll'ах ошибки.

например. (и обратите внимание, что это с / FORCE: MULTIPLE, так что это предупреждение, дайте мне знать, если вы хотите ошибку без / FORCE: MULTIPLE, и я опубликую ее):

1>LIB_X.lib(LIB_X.dll) : warning LNK4006: "public: __thiscall std::vector<double,class std::allocator<double> >::~vector<double,class std::allocator<double> >(void)" (??1?$vector@NV?$allocator@N@std@@@std@@QAE@XZ) already defined in vtkCommon.lib(vtkInformationDoubleVectorKey.obj);

Я пытался использовать / FORCE: MULTIPLE, и сначала это казалось чудом, но я получаю случайные ошибки в коде, которые в основном приводят к куче ошибок. Я решил удалить все ссылки на LIB_X из основного проекта и создал статическую библиотеку, которая будет обрабатывать все содержимое LIB_X. Я не эксперт по C ++, поэтому я не уверен, как он справляется с конфликтами библиотек, когда вы используете предварительно скомпилированную библиотеку, но я все еще получал ошибки конфликтования библиотек при связывании моей статической библиотеки с моим основным проектом, поэтому я все еще должны использовать / FORCE: НЕСКОЛЬКО.

Когда у меня была статическая библиотека, казалось, что случайные ошибки исчезли, я смог многое сделать с методами LIB_X в основном проекте через статическую библиотеку, НО из ниоткуда, я добавил новый элемент данных в класс моего основного проекта (std :: vector of doubles), и внезапно я получил ошибку кучи в одном из методов моей статической библиотеки. Если бы я закомментировал новый элемент данных, метод статической библиотеки работал бы нормально. Ненавижу приводить текущую ошибку, потому что, честно говоря, я не уверен, стоит ли ее изучать, но в любом случае она полезна:

примечание: в строке 151 происходит сбой xutility, всплывает утверждение: "file: dbgheap.c строка: 1279 выражение: _CrtIsValidHeapPointer (pUserData)"

Ошибка возникает после добавления векторного вектора double к векторному вектору double, сбою в строке push_back:

std::vector<std::vector<double>> tmpVec;
for(srvl_iter = srvl.begin(); srvl_iter != srvl.end(); ++srvl_iter)
{
 tmpVec.push_back((*srvl_iter).getControlPoints());
}
this->_splines.push_back(tmpVec); //CRASH

Это начало падать здесь только тогда, когда я добавил новый элемент данных в свой основной проект (отдельно от статической библиотеки!). Комментирование нового элемента данных убирает ошибку.

std::vector<std::vector<std::vector<double>>> _geometry; 

Итак, / FORCE: MULTIPLE кажется плохим, я получаю случайные ошибки, которые просто не имеют смысла для меня. Есть ли другие решения? Я облажался? Могу ли я что-нибудь сделать со связыванием LIB_X VTK?

Ответы [ 2 ]

1 голос
/ 10 января 2010

Я столкнулся с кучей LNK4006 ошибок при связывании моего приложения с библиотекой (назовите ее библиотекой LIB_Y), которая интенсивно использовала std::vector<std::string>, что я также сделал в своем приложении. После нескольких экспериментов я нашел одно работающее решение - обернуть LIB_Y в отдельную DLL, которая вызывает LIB_Y (скажем, LIB_Y_WRAPPER), а затем связать основное приложение с LIB_Y_WRAPPER.

Чтобы опробовать мое предложение, вам необходимо:

  1. Измените свою "статическую библиотеку, которая обрабатывает все содержимое LIB_X", из статического проекта LIB в проект DLL (который я назову LIB_X_WRAPPER).
  2. Убедитесь, что заголовочные файлы LIB_X_WRAPPER не содержат никаких заголовочных файлов LIB_X. Это действительно важно , потому что оболочка должна полностью изолировать ваше приложение от типов данных, объявленных в заголовочных файлах LIB_X (таких как std::vector<double>). Обращайтесь только к заголовочным файлам LIB_X из исходных файлов LIB_X_WRAPPER.
  3. Измените объявление всех классов и функций в вашей статической библиотеке, чтобы обеспечить их экспорт из DLL (см. этот ответ , если вам нужны подробности об экспорте из DLL).

Это решение сработало для меня, потому что оно сохранило инстанцирование (сгенерированные компилятором функции) класса std::vector<std::string>, используемого LIBY, полностью отдельным от инстанцирования std::vector<std::string> в моем приложении.

Кроме того, я подозреваю, что причина сбоя, который вы видите (вы комментируете это в деструкторе std::vector<double>), заключается в том, что экземпляр std::vector<double> в вашем приложении отличается от экземпляра в LIB_X.

0 голосов
/ 10 января 2010

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

Некоторые библиотеки требуют, чтобы вы включали вещи в определенном порядке. Я не уверен, почему именно потому, что мне кажется, что я сдаюсь и говорю, что вы не можете правильно проектировать библиотеку, но это печальный факт. До тех пор, пока вы не включите этот lib_x нигде, кроме vtk, все будет хорошо.

Однако они могут сражаться за какой-то ресурс или использовать что-то ненадлежащее, что делает невозможным совместную работу. Если вы можете заставить компиляцию работать нормально, разделив их, и она все равно не работает, тогда да, вам просто не повезло, потому что это просто неудача в том, как был разработан этот lib_x, и так как он настолько неясен, он вряд ли был тщательно отлажен от всех видов использования. Когда что-то не используется широко, оно обычно оказывается тем, что работает на машине и проекте разработчика, но не обязательно на чьем-либо еще.

...