Vorgehen bei Linkerfehlern

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
Jonathan
Establishment
Beiträge: 2398
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Vorgehen bei Linkerfehlern

Beitrag von Jonathan »

Ich habe ein bisschen Renderkram in eine Lib ausgelagert, die ich dann im Spiel benutze. Der Viewer, der nur diese Lib benutzt, funktioniert. Das Spiel hat neuerdings Linkerfehler, wobei eine Funktion, die definitiv in der Lib implementiert ist nicht gefunden wird, sowie eine ganze Menge Kram aus Assimp (_inflateEnd, _inflate, _inflateInit2_, _infalteSetDictionary, _inflateRest, _crc32, _get_crc_table).
Der Editor für das Spiel findet die glewInit nicht, die auch in meiner Lib drin ist, und vom Spiel gefunden wird.

Das ganze erscheint mir überaus willkürlich. Den AssimpKram benutze ich ja nur über die Lib, welche im Viewer funktioniert. Die eine Methode aus der Lib, die das Spiel nicht findet, ist dort auf jedne Fall implementiert und machte sonst auch keine Probleme. Und das mit dem glewInit ergibt auch keinen Sinn, ich habe alle Einstellungen schon zig mal überprüft und hunderte male einen kompletten Rebuild gemacht, es hilft alles nix.

Gut, der Linker sagt einfach nur "find ich net". Wie kann ich jetzt irgendwie dem Fehler systematisch auf die Schliche kommen? Immerhin ist das hier nicht der erste Linkerfehler, der sich nicht kurz und knapp erledigen lässt, sondern C++ scheint sowas irgendwie toll zu finden. (Manchmal möchte ich echt einen "Ich hasse C++"-Thread starten...)
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Vorgehen bei Linkerfehlern

Beitrag von BeRsErKeR »

Kann es eventuell sein, dass du mal statisch und mal dynamisch linkst? Ansonsten auch gucken ob die Methoden richtig exportiert/importiert werden. Gerade unter Windows gibt es da ja ein paar Dinge zu beachten mit dem dllspec usw.
Ohne Input kein Output.
Benutzeravatar
Jonathan
Establishment
Beiträge: 2398
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Vorgehen bei Linkerfehlern

Beitrag von Jonathan »

Nein, ich linke sowohl die Lib als auch Assimp immer statisch. Dann fällt das mit dem dllspec raus, denke ich?
WIe könnte ich sonst noch nach dem Fehler suchen? Irgendwelche Tools, die mir mehr Informationen liefern?
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

Re: Vorgehen bei Linkerfehlern

Beitrag von kimmi »

Hast du die gleiche Runtime eingestellt? Also in der Regel bei Projecteigenschaften-> C /C++ -> Codegenerierung -> Runtime -> Multithreaded Dll bei Lib + allen anderen? Die Symbole klingen nach Runtime-spezifischen Symbolen.

Gruß Kimmi
Benutzeravatar
Jonathan
Establishment
Beiträge: 2398
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Vorgehen bei Linkerfehlern

Beitrag von Jonathan »

Nein, überall ist Multithreaded Dll eingestellt (bzw. Multithreaded Debug Dll).
Ich hab noch ein paar Warnungen behoben und die windows.h rausgeschmissen, weil es in irgendwelchen anderen Windows Header zu doppelt definierten Makros kam, aber das hat auch nix geändert. Bis auf ein paar Stellen, wo ich nicht explizit gecastet habe, ist der Code jetzt warnungsfrei, aber geht immer noch nicht.

Hier mal die genauen Linker Fehler:

Code: Alles auswählen

1>     Bibliothek "..\..\..\bin\Game.lib" und Objekt "..\..\..\bin\Game.exp" werden erstellt.
1>SceneManager.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""protected: virtual void __thiscall Mrl::AmbientLight::ActivateSub(unsigned int,unsigned int,class CMatrix4x4 const &)" (?ActivateSub@AmbientLight@Mrl@@MAEXIIABVCMatrix4x4@@@Z)".
1>Assimp.lib(BlenderLoader.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "_inflateEnd".
1>Assimp.lib(XFileParser.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "_inflateEnd".
1>Assimp.lib(unzip.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "_inflateEnd".
1>Assimp.lib(BlenderLoader.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "_inflate".
1>Assimp.lib(XFileParser.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "_inflate".
1>Assimp.lib(unzip.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "_inflate".
1>Assimp.lib(BlenderLoader.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "_inflateInit2_".
1>Assimp.lib(XFileParser.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "_inflateInit2_".
1>Assimp.lib(unzip.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "_inflateInit2_".
1>Assimp.lib(XFileParser.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "_inflateSetDictionary".
1>Assimp.lib(XFileParser.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "_inflateReset".
1>Assimp.lib(unzip.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "_crc32".
1>Assimp.lib(unzip.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "_get_crc_table".
1>..\..\..\bin\Game.exe : fatal error LNK1120: 8 nicht aufgelöste externe Verweise.
Wie man sieht, eine Funktion in Mrl (die dort aber definitiv drin ist) und ne ganze Menge Assimpkram (welchen ich nur über Mrl benutze). Das macht alles keinen Sinn, weil er alles finden müsste, und es bei dem Viewer ja auch tut.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Schrompf
Moderator
Beiträge: 4886
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: Vorgehen bei Linkerfehlern

Beitrag von Schrompf »

Schau mal in Deine Assimp-Buildsettings. Es gibt ein spezielles Define, dass man bei Assimp angeben kann, so dass es keine eigene zlib mitkompiliert, sondern sich auf eine extern dazugelinkte ZLib verlässt. Wenn Du das Define gesetzt hast, würde das die den Effekt erklären. Denkbar wäre allerdings auch ein C-C++-Konflikt - unter C++ werden wegen möglicher Operatorüberladungen die Funktionsnamen mit Parameterinfos vermischt. Wenn Du z.B. irgendwo die zlib-Funktionen innerhalb eines "extern C"-Blocks deklariert hast, an anderer Stelle aber ohne das "extern C" deklarierst und kompilierst, würden auch solche Fehlermeldungen kommen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Jonathan
Establishment
Beiträge: 2398
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Vorgehen bei Linkerfehlern

Beitrag von Jonathan »

Aber ich habe nie explizit was mit zlib gemacht, ich habe immer nur Assimp direkt benutzt. Ich hab nie zlib so runter geladen und isntalliert, und in den Projektoptionen vom Viewer steht schon gar nix wegen zlib, von daher sollte es doch eigentlich alles finden...
Gibts evtl. n Tool, mit dem man gucken kann, was in die lib exportiert wurde?
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

Re: Vorgehen bei Linkerfehlern

Beitrag von kimmi »

Ja, das gibt es. Es heisst dumpbin.exe. Du kann dieses im VS-Eingabeprompt benutzen, dann brauchst du nicht deine PATH-Variable anzupassen. Oder du suchst im Netz mal nach depends.exe, das bringt noch gleich eine GUI mit.
Womit hast du die Workspaces von assimp und deinem Code generiert? Das PK3-Archiv imlpementiert für den BSP-Loader benutzt die unzip-Library, die wiederum auf zlib basiert. Und meines Wissens nach ist zlib per Default Teil von Assimp. Allerdings muss man dem Studio explizit sagen, dass man den zlib-code als C-Code zu übersetzen hat ( da hättest du aber Compiler-Fehler ). Für mich riecht das nun mehr nach Call-Convention zwischen der Contrib-Lib zlib und dem Rest.
Und sorry für meine falsch Färte, ich habe die Namen für Runtime-Zeug statt zlib-Zeug gehalten.

Gruß Kimmi
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Vorgehen bei Linkerfehlern

Beitrag von eXile »

Schau dir die DLLs erst einmal mit depens an. Ich habe gerade inkonsistente Calling-Conventions im Verdacht (dabei werden dann die Namen falsch dekoriert).
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Vorgehen bei Linkerfehlern

Beitrag von BeRsErKeR »

DLLs beim statischen Linken?
Ohne Input kein Output.
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Vorgehen bei Linkerfehlern

Beitrag von eXile »

BeRsErKeR hat geschrieben:DLLs beim statischen Linken?
Dann ersetze halt DLL durch Library, ich würde mir trotzdem dort die Calling-Convention mal reinziehen.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Vorgehen bei Linkerfehlern

Beitrag von Krishty »

Schrompf hat geschrieben:Schau mal in Deine Assimp-Buildsettings. Es gibt ein spezielles Define, dass man bei Assimp angeben kann, so dass es keine eigene zlib mitkompiliert, sondern sich auf eine extern dazugelinkte ZLib verlässt.
Falls er meine Assimp-Projektdateien aus diesem Thread benutzt, ist es das.

Hat schon einen Sinn, wenn ich das dazuschreibe; meine Projekte sind immer sehr eigen konfiguriert ;) Entweder mein beigelegtes zlib-Projekt linken oder ASSIMP_BUILD_NO_OWN_ZLIB aus den Präprozessorsymbolen entfernen und zlib manuell aus dem Repository ins Projekt hinzufügen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Jonathan
Establishment
Beiträge: 2398
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Vorgehen bei Linkerfehlern

Beitrag von Jonathan »

Ok, das mit dem zlib hat schonmal funktioniert. Vermutlich war zlib einfach in den Qt Klassen mit drinne, darum ging es im Viewer, im Spiel aber nicht.
Allerdings hab ich jetzt weiterhin das Problem, dass 2 Funktionen, die in Mrl.lib drin sein müssen nicht gefunden werden. Der Editor findet die glewInit nicht, die Spiel und Viewer anscheinend finden, und das Spiel findet Mrl::AmbientLight::ActivateSub nicht, und ich finde beim besten willen nicht, wie das nich definiert sein könnte...
Ich werde jetzt mal dumpbin und depends ausprobieren (eXile, meintest du damit den Dependency Walker, das ist jedenfalls das, was ich beim Suchen finde?) und gucken ob ich da weiter komme. Aber nur noch 1 Linkerfehler pro Projekt, das ist doch mal was :)

[edit]

Ok, hier ist schonmal was: Die Fehlermeldung beim Compilieren von Game:

Fehler 1 error LNK2001: Nicht aufgelöstes externes Symbol ""protected: virtual void __thiscall Mrl::AmbientLight::ActivateSub(unsigned int,unsigned int,class CMatrix4x4 const &)" (?ActivateSub@AmbientLight@Mrl@@MAEXIIABVCMatrix4x4@@@Z)".

Was dumpbin findet:
60501020 flags
Code
COMDAT; sym= "protected: virtual void __thiscall Mrl::AmbientLight::ActivateSub(unsigned int,unsigned int,class Mrl::CMatrix4x4 const &)" (?ActivateSub@AmbientLight@Mrl@@MAEXIIABVCMatrix4x4@2@@Z)
16 byte align
Execute Read

Und wenn ich die Funktion tatsächlich auskommentiere und den Viewer erstellen will, findet er die selbe Funktion nicht, die sonst drin ist, also ?ActivateSub@AmbientLight@Mrl@@MAEXIIABVCMatrix4x4@2@@Z, während hingegen das Spiel scheinbar nach ?ActivateSub@AmbientLight@Mrl@@MAEXIIABVCMatrix4x4@@@Z sucht (die letzten paar Zeichen sind anders).
WIe kann das kommen? Kann es irgendwie an dem typedef von "typedef CMatrix mrlMatrix;" liegen?
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Vorgehen bei Linkerfehlern

Beitrag von Krishty »

Jonathan hat geschrieben:und das Spiel findet Mrl::AmbientLight::ActivateSub nicht, und ich finde beim besten willen nicht, wie das nich definiert sein könnte...
#error einbauen um zu gucken, ob sie überhaupt kompiliert wird. Wenn ja, Deklaration und Definition posten.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Jonathan
Establishment
Beiträge: 2398
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Vorgehen bei Linkerfehlern

Beitrag von Jonathan »

Das mit dem #error hab ich gecheckt, sie wird kompiliert. Ich poste mal den Code:

Code: Alles auswählen

#include "AmbientLight.hpp"

#include <sstream>
using namespace std;

namespace Mrl
{

std::string AmbientLight::GetFragmentGlobalsSub(unsigned int ID)
{
	return string();
}

std::string AmbientLight::CalcDiffuseColor(unsigned int ID)
{
	stringstream s;
	s << " " << GetColor(ID) << " * MaterialColor //Ambient Light " << ID << "\n";
	return s.str();
}

void AmbientLight::ActivateSub(GLuint ShaderProgram, unsigned int ID, const Mrl::mrlMatrix &LightTransformation)
{
}

}

Code: Alles auswählen

#ifndef MRL_AMBIENT_LIGHT
#define MRL_AMBIENT_LIGHT


#include "Types.hpp"
#include "Light.hpp"


namespace Mrl
{

class AmbientLight : public Light
{	
public:
	virtual std::string CalcDiffuseColor(unsigned int ID); ///< generates the lightcalculation source
protected:
	virtual std::string GetFragmentGlobalsSub(unsigned int ID); ///< generates the variable declaration source
	virtual void ActivateSub(GLuint ShaderProgram, unsigned int ID, const mrlMatrix& LightTransformation);///< set the variables in the shader, to activate this light
};

}

#endif
Wie gesagt, ich hab noch ein bisschen weiter getestet, (siehe edit im vorherigen Post).
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Vorgehen bei Linkerfehlern

Beitrag von Krishty »

Ups, habe den Nachtrag übersehen … mit Name Mangling kenne ich mich leider nicht aus. Sind denn CMatrix4x4 und Mrl::CMatrix4x4 dasselbe? D.h. existieren keine zwei Definitionen der Klasse CMatrix4x4 (einmal im globalen Namespace und einmal in Mrl)?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Jonathan
Establishment
Beiträge: 2398
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Vorgehen bei Linkerfehlern

Beitrag von Jonathan »

So, mittlerweile funktioniert alles :)

Das mit der Matrix war ne ganz dumme Sache. Ich habe scheinbar im Spiel und in Mrl die selbe Matrixklasse benutzt, nur in Mrl die irgendwann mal in den namespace Mrl gepackt. Da ich clevererweise die gleiche Datei von der Matrixklasse benutzt habe, waren auch die include guards gleich, so hab ich nicht gemerkt, dass ich die Klasse doppelt drin hatte (ich sollten denen wirklich präfixe verpassen...)
Das Problem mit dem Editor war die alte Nummer, dass man GLEW_STATIC definieren muss. Allerdings hab ich keine Ahnung, wie der Viewer so kompilieren konnte, aber naja, jetzt geht es überall.

Nochmal ein herzliches Dankeschön für alle, die mir bei diesem demotivierenden Fehler geholfen haben!
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Antworten