2 Stimmen

VC++ Bibliothekskonfliktproblem

Ich arbeite an einem C++-Projekt, das Qt (GUI-Library), VTK (Graphics-Library) und eine andere Bibliothek verwendet, die so obskur ist, dass ich ihren Namen nicht erwähnen werde und stattdessen LIB_X nennen werde. Das Projekt verwendet Qt für die GUI-Komponenten und VTK (genauer gesagt die von VTK bereitgestellte QVTKWidget-Erweiterung, die Qt unterstützt) zur Darstellung der Geometrie... und es verwendet LIB_X, um Geometrie zu sammeln und zu manipulieren.

Das Problem ist, dass sich herausstellt, dass LIB_X tatsächlich VTK verwendet (wo und wie, weiß ich nicht, es ist Closed Source). Anfangs gab es kein Problem, das Kompilieren mit beiden Bibliotheken verlief gut, aber irgendwann habe ich eine bestimmte (und dringend benötigte) LIB_X-Funktion aufgerufen und das Kompilieren führte zu einer Vielzahl von Fehlern wie 'bla bla etwas über eine in der LIB_X-DLL bereits definierte VTK-Lib/Objekt'.

Zum Beispiel (und beachten Sie, dass dies mit /FORCE:MULTIPLE ist, also nur eine Warnung hier, lassen Sie mich wissen, wenn Sie den Fehler ohne /FORCE:MULTIPLE möchten, und ich werde ihn posten):

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

Ich habe versucht, /FORCE:MULTIPLE zu verwenden, und es schien zuerst ein Wunder zu sein, aber ich bekomme zufällige Fehler im Code, die meistens Heap-Fehler verursachen. Ich habe beschlossen, alle Verweise auf LIB_X aus dem Hauptprojekt zu entfernen und eine statische Bibliothek zu erstellen, die sich um alle LIB_X-Angelegenheiten kümmern würde. Ich bin kein C++-Experte, daher bin ich mir nicht sicher, wie es mit Bibliothekskollisionen umgeht, wenn Sie eine vorkompilierte Bibliothek verwenden, aber ich habe immer noch Bibliothekskollisionsfehler erhalten, als ich meine statische Bibliothek in mein Hauptprojekt eingebunden habe, also muss ich immer noch /FORCE:MULTIPLE verwenden.

Nachdem ich die statische Bibliothek hatte, schien es, als wären die zufälligen Fehler verschwunden. Ich konnte viele Dinge mit LIB_X-Methoden im Hauptprojekt über die statische Bibliothek machen, ABER aus dem Nichts habe ich einem neuen Datenmember zur Klasse meines Hauptprojekts hinzugefügt (eine std::vector von doubles) und plötzlich bekam ich einen Heap-Fehler in einer meiner Methoden der statischen Bibliothek. Wenn ich den neuen Datenmember auskommentiert habe, lief die Methode der statischen Bibliothek gut. Ich möchte den aktuellen Fehler nicht angeben, weil ich ehrlich gesagt nicht sicher bin, ob es sich lohnt, ihn zu untersuchen, aber hier ist er trotzdem, falls er hilfreich sein kann:

Beachten Sie: es stürzt auf xutility in etwa Zeile 151 ab mit der Assertion: "Datei: dbgheap.c Zeile: 1279 Ausdruck: _CrtIsValidHeapPointer(pUserData)"

Der Fehler tritt nach dem Hinzufügen eines Vektor-Vektors double zu einem Vektor-Vektor-Vektor double auf und stürzt beim push_back ab:

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

Es begann erst hier abzustürzen, als ich einen neuen Datenmember zu meinem Hauptprojekt hinzugefügt habe (getrennt von der statischen Bibliothek!) Das Auskommentieren des neuen Datenmitglieds hebt den Fehler auf.

std::vector>> _geometry; 

Also, /FORCE:MULTIPLE scheint schlecht zu sein, ich bekomme zufällige Fehler, die für mich keinen Sinn ergeben. Gibt es andere Lösungen? Bin ich verloren? Kann ich etwas mit der Verlinkung von VTK durch LIB_X machen?

1voto

mcdave Punkte 2510

Ich bin auf eine Reihe von LNK4006-Fehlern gestoßen, als ich meine App mit einer Bibliothek (nennen wir sie Bibliothek LIB_Y) verknüpfte, die stark von std::vector Gebrauch machte, was ich auch in meiner App tat. Nach einigem Experimentieren fand ich eine Lösung, die funktionierte - verpacke LIB_Y in einer separaten DLL, die LIB_Y aufruft (nennen wir sie LIB_Y_WRAPPER) und verknüpfe dann die Haupt-App mit LIB_Y_WRAPPER.

Um meinen Vorschlag auszuprobieren, müssen Sie folgendes tun:

  1. Ändern Sie Ihr "statisches LIB, das alle LIB_X-Sachen handhabt", von einem statischen LIB-Projekt in ein DLL-Projekt (das ich LIB_X_WRAPPER nennen werde).
  2. Vergewissern Sie sich, dass die Headerdateien von LIB_X_WRAPPER keine der LIB_X-Headerdateien enthalten. Dies ist wirklich wichtig, da der Wrapper Ihre App komplett von den in den LIB_X-Headerdateien deklarierten Datentypen isolieren muss (wie z. B. std::vector). Verweisen Sie nur aus den Quelldateien von LIB_X_WRAPPER auf die Headerdateien von LIB_X.
  3. Ändern Sie die Deklaration aller Klassen und Funktionen in Ihrer statischen Bibliothek, um sicherzustellen, dass sie aus der DLL exportiert werden (siehe diese Antwort, wenn Sie Details zum Exportieren aus einer DLL benötigen).

Diese Lösung hat bei mir funktioniert, weil sie die Instantiierung (vom Compiler generierte Funktionen) der von LIBY verwendeten std::vector-Klasse vollständig von der Instantiierung von std::vector in meiner App getrennt hat.

Übrigens vermute ich, dass die Ursache des Absturzes, den Sie sehen (Sie kommentieren, dass es im Destruktor von std::vector ist), darin liegt, dass die Instanziierung von std::vector in Ihrer App sich von der in LIB_X unterscheidet.

0voto

Das Auskommentieren ist wahrscheinlich nur reines Glück - wenn Sie den Heap beschädigen, sehen Sie es nicht immer sofort, aber ein stl-Vektor wird Dinge hin und her zuweisen und freigeben, daher ist es kein Wunder, dass er den Fehler findet.

Einige Bibliotheken erfordern, dass Sie Dinge in einer bestimmten Reihenfolge einfügen. Ich bin mir nicht sicher, warum genau, denn für mich scheint es, als würde man aufgeben und sagen, dass man eine Bibliothek nicht richtig entwerfen kann, aber es ist eine traurige Tatsache. Solange diese lib_x an keiner Stelle eingefügt wird, an der Sie vtk einfügen, sollte es in Ordnung sein.

Allerdings könnten sie um eine Ressource kämpfen oder etwas falsch verwenden, was es ihnen unmöglich macht, zusammen zu arbeiten. Wenn es Ihnen gelingt, das Kompilieren in Ordnung zu bringen, indem Sie sie isolieren und es dennoch fehlschlägt, dann sind Sie einfach vom Pech verfolgt, weil es einfach an der Art liegt, wie diese lib_x entworfen wurde, und da sie so obskur ist, wird sie wahrscheinlich nicht vollständig gegen alle Verwendungen debuggt. Wenn etwas nicht weit verbreitet ist, endet es in der Regel damit, dass es auf der Entwicklermaschine und im Projekt funktioniert, aber möglicherweise bei niemand anderem.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X