Absurdes Programmverhalten

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

Absurdes Programmverhalten

Beitrag von Jonathan »

Ich glaube ich habe in meinem Programm so etwas wie undefiniertes Verhalten, aber ich habe absolut keine Ahnung, wie ich dem auf die Schliche kommen soll.

Ich habe also mein Spiel und das benutzt Assimp zum Modelle laden. Ich bin mir nicht sicher, ob es damit etwas zu tun hat, aber ich habe einmal eine Kleinigkeit am OgreImporter für Assimp geändert (nur eine Formatierungssache), ohne die dll neu zu kompilieren. Jetzt hing sich das Spiel beim Laden auf. Also bau ich einen Debugbuild, starte Debugging, aber der läuft ohne Probleme durch. Ok, sowas hat man schonmal ab und zu. Kurioserweise konnte ich aber den Releasebuild im Debugmodus von VC starten, dann lief dieser auch ohne Probleme. Irgendwann hab ich die Assimp.dll dann neu gebaut und installiert, aber das Problem blieb weiterhin bestehen. Weil mir das ganze zu bunt wurde, habe ich neuen Neustart gemacht, und danach lief es bei mir auch direkt.
Bei meinem Kollegen blieb es dann aber auch beim laden hängen. Also habe ich ihn gebeten, es über eine .bat Datei zu starten, die die Konsolenausgaben in eine Textdatei schreibt, damit er mir die Ausgabe leichter schicken kann. Startete er das Spiel über diese bat-Datei lief es dann aber auf einmal rund. Auch eine andere bat-Datei die einfach nur die exe startet lief dann. Also habe ich ihn gebeten auch einen Neustart zu machen, der hat bei ihm aber nichts bewirkt. Daraufhin habe ich ihn gebeten, die exe-Datei umzubenennen und siehe da, es lief auf einmal. Als er den Namen wieder zurück geändert hat, lief es dann immer noch.
Gut, dann wollte ich mal den aktuellen Spielzwischenstand archivieren und habe das ganze Spiel einmal kopiert. Diese Kopie blieb dann beim normalen starten hängen, während das Original wunderbar startete. Also hab ich eine Konsole aufgemacht und darüber die Kopie gestartet, und siehe da, es läuft. Weil mir das ganze zu bunt wurde, habe ich die Kopie dann noch einmal in einen anderen Ordner kopiert, und die Version lief dann wieder.
Das es nur zufällig mal startet oder nicht kann ich quasi ausschließen, ich habe die 3 Versionen mehrmals gestartet, 2 liefen immer, eine nie, es sei denn, man startet sie über die Konsole.

Vielleicht verschwindet der Bug genauso heimlich, wie er gekommen ist, aber ich mag es absolut nicht, wenn irgendwas rumzickt und ich keine Ahnung habe, wieso. Ja, irgendwelche Tips, was da los sein könnte?
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Absurdes Programmverhalten

Beitrag von dot »

Wenn du es aus dem Debugger startest läuft es reproduzierbar immer? Könnte vielleicht was mit uninitialisierten Werten zu tun haben? Du kannst mal versuchen den Debug Heap so gut es geht auszuschalten und schauen ob der Debug Build dann auch nicht mehr funktioniert.
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4263
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: Absurdes Programmverhalten

Beitrag von Chromanoid »

Eine mögliche an den Haaren herbei gezogene Erklärung :) Vielleicht ein Virenscanner o.Ä. der "Doppelklick-Startvorgänge" anders behandelt als einen Start durch Konsole/Batch. Der Virenscanner könnte dann irgendeinen problematischen Vorgang anders blockieren/verzögern als beim direkten Start und so könnte dann das seltsame Verhalten entstehen. Dass es plötzlich dauerhaft läuft, könnte dann daran liegen, dass die Datei als unschädlich markiert wurde.
btw liegen unterschiedliche Betriebssysteme vor? Kompatibilitätskram von Windows kann glaube ich auch interessante Sachen verursachen.
Andre
Establishment
Beiträge: 186
Registriert: 21.12.2011, 20:33

Re: Absurdes Programmverhalten

Beitrag von Andre »

Deine Erklärung könnte gut möglich sein. Avast! hat bei mir, als ich es erst frisch installiert hatte, angefangen [w]tech nach dem starten (auch direkt aus VisualStudio, auch im Debugmode) in eine Sandbox zu packen. Und da lief es halt einfach nicht drin ;)
Möglich ist das auf jeden Fall.
Benutzeravatar
Jonathan
Establishment
Beiträge: 2395
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Absurdes Programmverhalten

Beitrag von Jonathan »

Ja, sowas in der Art könnte sein. Nur hab ich keinen Virenscanner installiert. Aber vielleicht macht ja irgendein anderes Programm im Hintergrund blödsinn, heutzutage laufen ja die wildesten Hintergrundprozesse. Vielleicht auch eine komische Art von Virus? Aber die Version, die ich meinem Kollegen über Dropbox kopiert habe, scheint virenfrei zu sein.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Absurdes Programmverhalten

Beitrag von CodingCat »

Ich tippe auf uninitialisierte Variablen und Debug Heap, siehe dot. Je nachdem, in welchem Kontext du startest, werden solche Variablen darin anders oder gar nicht initialisiert. Ich bin immer noch für ein uninitialized_t in C++, optional mit Zwang zur expliziten Konstruktion. ;)
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Absurdes Programmverhalten

Beitrag von Krishty »

Um das herauszufinden, empfehle ich, die Allokationsoperatoren derart abzuändern, dass sie den Speicher mit anderen Werten überschreiben. Ich habe um die 30 uninitialisierten Variablen in einem Projekt gefunden, indem der Speicher je nach Programmstart-Systemzeit mit 0x00000000, 0x00000001 und 0xFFFFFFFF initialisiert wurde.

Der MS-CRT-Heap bietet afaik auch irgendwo eine Funktion, die Werte einzustellen, aber ich habe die nie benutzt und weiß auch gerade nicht, wie sie heißen. Bei besonders hartnäckigen Fällen kann ich empfehlen, direkt VirtualAlloc() zu benutzen; zusätzliche Schutzseiten hinter jeder Allokation einzusetzen und Seiten bei der Freigabe bloß zu sperren.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Absurdes Programmverhalten

Beitrag von eXile »

Krishty hat geschrieben:empfehle ich, die Allokationsoperatoren derart abzuändern
Damit wir uns verstehen: Du meinst, operator new zu überladen? Nicht, dass mir hier irgendeine tolle Debugginghilfe gerade entgeht.

Und, falls man die CRT benutzt, hat die auch schon ganz gute Möglichkeiten; schaut mal ins crt_dbg1- und crt_dbg2-Sample rein. Natürlich kann die aber keine Lesezugriffe außerhalb allokierter Speicherbereiche innerhalb der Page-Grenze abfangen; wobei ich immer noch nach einer Möglichkeit suche, gleichzeitig auf Underrun und Overrun zu testen. Die aktuelle Vorgehensweise ist da ja, die Allokation am Anfang bzw. am Ende einer Page zu erstellen.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Absurdes Programmverhalten

Beitrag von Krishty »

eXile hat geschrieben:
Krishty hat geschrieben:empfehle ich, die Allokationsoperatoren derart abzuändern
Damit wir uns verstehen: Du meinst, operator new zu überladen? Nicht, dass mir hier irgendeine tolle Debugginghilfe gerade entgeht.
Ja; ich rede nur vom Plural, weil man new z.B. auch klassenlokal überladen kann. Das sollte man dann nicht vergessen.
eXile hat geschrieben:Natürlich kann die aber keine Lesezugriffe außerhalb allokierter Speicherbereiche innerhalb der Page-Grenze abfangen; wobei ich immer noch nach einer Möglichkeit suche, gleichzeitig auf Underrun und Overrun zu testen. Die aktuelle Vorgehensweise ist da ja, die Allokation am Anfang bzw. am Ende einer Page zu erstellen.
Vielleicht: Seite komplett sperren; Exception Handler installieren, der die Adresse prüft; Weitermachen, falls die Adresse gültig ist, und ansonsten in den Debugger springen. Dürfte schön langsam werden, aber Speicherfehler zu finden ist ja an sich sehr zäh.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Jonathan
Establishment
Beiträge: 2395
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Absurdes Programmverhalten

Beitrag von Jonathan »

Nach dem das Problem zufällig verschwunden war, ist es jetzt wieder zufällig aufgetaucht. Ich habe die Nase jetzt voll und will die Ursache finden. Ich denke, dass es an meinem Assimp-Ogre Importer liegt, während dessen bleibt er nämlich immer hängen.
Die Ideen hier hören sich nicht schlecht an, aber gibt es eventuell weiterführende Informationen oder gar Tutorials dazu? Weil mit sowas habe ich mich noch nie beschäftigt, aber es scheint, jetzt sei ein guter Zeitpunkt dafür.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: Absurdes Programmverhalten

Beitrag von Helmut »

Was meinst du denn genau mit das Programm hängt sich auf?
Falls es in einer Endlosschleife landet kannst du den Debugger ja nachträglich anhängen. Dann dürftest du selbst ohne Symbole recht schnell die Schleife finden.
Benutzeravatar
Jonathan
Establishment
Beiträge: 2395
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Absurdes Programmverhalten

Beitrag von Jonathan »

Naja, ich gebe vor dem Assimp Import etwas aus und danach, der der Text der danach kommen sollte, kommt halt einfach nie.
Das Problem ist, wenn ich die Releaseversion im Debugmode starte, läuft es durch. Es knallt ansich nur, wenn ich es normal starte.
Aber ich denke, eine intensive Suche nach Speicher-/Initialisierungsfehlern könnte auch Fehler zu Tage bringen, die sich bisher vielleicht noch gar nicht geäußert haben. Daher würde ich gerne mehr oder weniger systematisch dadurch gehen, anstatt so lange rumzubasteln, bis es durch Zufall wieder geht.

[edit]Noch ein Grund es vernünftig zu machen: Ich habe gerade an der Gui gebastelt und das Spiel lädt das Modell wieder. Ich glaube kaum, dass ich den Fehler, durch traditionelles durchsteppen finden werde.[/edit]
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Jonathan
Establishment
Beiträge: 2395
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Absurdes Programmverhalten

Beitrag von Jonathan »

*push*
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Jonathan
Establishment
Beiträge: 2395
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Absurdes Programmverhalten

Beitrag von Jonathan »

Ich hab was gefunden. Nachdem in einem anderen Thread Valgrind erwähnt wurde, habe ich Dr. Memory ausprobiert, um das ganze unter Windows zu debuggen. Dadurch habe ich in meinem Ogre Importer ein MemoryLeak und einen falschen Speicherzugriff gefunden:

Code: Alles auswählen

vector<char> FileData(MaterialFile->FileSize());
MaterialFile->Read(&FileData[0], MaterialFile->FileSize(), 1);
BaseImporter::ConvertToUTF8(FileData);

FileData.push_back('\0');//terminate the string with zero, so that the ss can parse it correctly
ss << &FileData[0];
Die vorletzte Zeile habe ich jetzt hinzugefügt. Vorher wurde der Stringstream wegen der fehlenden 0 vermutlich extrem groß, woraufhin das Parsen danach ungefähr unendlich lange dauerte (oder er kam gar nicht soweit). Gut, mein Spiel funktioniert zwar jetzt, aber das hieß ja auch früher schon nichts. Aber ich gehe mal davon aus, dass das das Problem war, mehr hat Dr. Memory in meinem Importer jedenfalls nicht gefunden.
Es gab übrigens noch eine ganze Reihe weiterer Fehlermeldungen, die meisten in DirectX oder Treiberdlls. Aber auch einige in Assimp / Assimp Viewer. Die Logdatei ist insgesamt 6 MB, aber bei Gelegenheit zeige ich mal was, oder schaue, ob ich selber ein paar Fehler beheben kann.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Absurdes Programmverhalten

Beitrag von eXile »

Jonathan hat geschrieben:Die Logdatei ist insgesamt 6 MB, aber bei Gelegenheit zeige ich mal was, oder schaue, ob ich selber ein paar Fehler beheben kann.
Da helfen Suppressions. Beispiel für Nvidia-Treiber:

Code: Alles auswählen

UNINITIALIZED READ
name=nvwgf2um.dll read errors
...
nvwgf2um.dll!*

POSSIBLE LEAK
name=nvwgf2um.dll leaks
...
nvwgf2um.dll!*

UNINITIALIZED READ
name=d3d11.dll read errors
...
d3d11.dll!D3D11CreateDevice
Benutzeravatar
Jonathan
Establishment
Beiträge: 2395
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Absurdes Programmverhalten

Beitrag von Jonathan »

Ah das sieht gut aus. Hast du auch irgendwelche Tipps, wie ich einen boost-Debug build bekomme, der trotzdem /MD und nicht /MDd benutzt? Das ist ja Voraussetzung für Dr Memory, aber ich finde in der b2 Doku keinen Flag dazu.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Absurdes Programmverhalten

Beitrag von eXile »

Das müsstest du als cxxflags angeben können. Wenn du damit auf die Schnauze fliegst, weil Boost vielleicht doch im Debug-Build Features aus der Debug-CRT braucht, musst du wohl gegen die Release-Version von Boost im deinem Debug-Build zum Testen mit Dr. Memory linken.

Der Vollständigkeit halber mal meine nunmehr erweiterte Suppression-Datei:

Code: Alles auswählen

UNINITIALIZED READ
...
nvwgf2um.dll!*

POSSIBLE LEAK
...
nvwgf2um.dll!*

LEAK
...
nvwgf2um.dll!*

WARNING
...
nvwgf2um.dll!*



UNINITIALIZED READ
...
d3d11.dll!D3D11CreateDevice 

POSSIBLE LEAK
...
d3d11.dll!D3D11CreateDevice

LEAK
d3d11.dll!*



UNINITIALIZED READ
...
d3d11SDKLayers.dll!*



UNINITIALIZED READ
...
d3d10warpNoD3D9.dll!Ordinal50

LEAK
...
d3d10warpNoD3D9.dll!SetInfoQueue  

LEAK
d3d10warpNoD3D9.dll!D3D10RefGetLastCreation



UNINITIALIZED READ
...
d3d11ref.dll!OpenAdapter10_2

UNINITIALIZED READ
d3d11ref.dll!D3DKMTCreateContext



UNINITIALIZED READ
...
dxgi.dll!*

POSSIBLE LEAK
...
dxgi.dll!*

LEAK
dxgi.dll!*



UNINITIALIZED READ
...
D3DCOMPILER_43.dll!D3DDisassemble10Effect



UNINITIALIZED READ
...
XINPUT1_3.dll!XInputGetKeystroke



UNINITIALIZED READ
USER32.dll!GetClassLongW



UNINITIALIZED READ
ntdll.dll!RtlAllocateHeap
MSVCR100.dll!malloc
MSVCR100.dll!operator new
*!std::_Tree_val<*

LEAK
ntdll.dll!RtlRunOnceBeginInitialize



INVALID HEAP ARGUMENT
*!std::_DebugHeapDelete<std::locale>
*!std::basic_streambuf<char,std::char_traits<char> >::~basic_streambuf<char,std::char_traits<char> >

INVALID HEAP ARGUMENT
*!std::_DebugHeapDelete<_RTL_CRITICAL_SECTION>
*!std::_Mutex::~_Mutex
*!std::basic_streambuf<char,std::char_traits<char> >::~basic_streambuf<char,std::char_traits<char> >

INVALID HEAP ARGUMENT
*!std::_DebugHeapDelete<std::locale>
*!std::ios_base::_Ios_base_dtor

INVALID HEAP ARGUMENT
*!std::_DebugHeapDelete<std::locale::facet>
*!std::_Fac_node::~_Fac_node

INVALID HEAP ARGUMENT
*!std::_DebugHeapDelete<std::_Fac_node>
*!_Fac_tidy

INVALID HEAP ARGUMENT
*!std::_DebugHeapDelete<void>
*!std::numpunct<char>::_Tidy

INVALID HEAP ARGUMENT
*!std::_DebugHeapDelete<std::locale::facet>
*!_Deletegloballocale
Bild

Da fragt man sich so langsam, warum Computer überhaupt noch booten. :|
Benutzeravatar
Jonathan
Establishment
Beiträge: 2395
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Absurdes Programmverhalten

Beitrag von Jonathan »

Danke. Nach endlosen rumprobieren, aufgeben und wieder neu Anfangen hab ich es jetzt geschafft. Die hätten ja ruhig dabei schreiben können, das vor den Falgs ein - stehen muss... So gings jedenfalls:

b2 serialization cxxflags=-MD link=static variant=debug,release
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Jonathan
Establishment
Beiträge: 2395
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Absurdes Programmverhalten

Beitrag von Jonathan »

Ich hänge leider immer noch fest. Ich konnte jetzt mein Programm mit allen Abhängigkeiten so kompilieren, dass die Release Runtime (/MD) benutzt wird. Allerdings kann ich es immer noch nicht Debuggen und DependencyWalker zeigt mir an, dass mein programm sowohl die Debug als auch die Release Runtime benötigt.
Jetzt habe ich also zum einen sichergestellt, dass die Releasebibliotheken von boost benutzt werden (hattest ja erwähnt, es könnte da Abhängigkeiten geben) und zum anderen die Linkereingabe angeschaut. Da wird jetzt eigentlich nichts mehr in der Debugversion gelinkt, was ich vorher nicht selber mit /MD kompiliert habe, aber trotzdem bleibt die Abhängigkeit zur Debugruntime.
Irgendwelche Ideen, wie ich herausfinden kann, wie diese Abhängigkeit zustande kommt?

[edit]Hat sich erledigt: Man musste für alle Projekte /Md einstellen und sichergehen, dass _Debug nicht definiert ist. Eigentlich habe ich ersteres in CMake für alle Projekte global eingestellt, letzteres für jedes Projekt eingestellt. Aber irgendwie hatte glew trotzdem die Debugruntime. Naja, jetzt scheint es zu gehen.[/edit]
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Jonathan
Establishment
Beiträge: 2395
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Absurdes Programmverhalten

Beitrag von Jonathan »

Nochmal ein kurzer Nachtrag:
Das mit glew lag daran, dass es ein C-Programm ist. In CMake hatte ich aber nur die CXXFlags gesetzt. Zur Übersicht:

CMAKE_CXX_FLAGS_DEBUG : "/D_DEBUG" löschen und aus "/MDd" ein "/MD" machen
CMAKE_C_FLAGS_DEBUG : genau das selbe
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Antworten