Gibt es eine Möglichkeit, dass ein Programm vor main() abstürzt?
Antworten
Zu viele Anzeigen?Die Antwort ist einfach: Ja .
Im Einzelnen lassen sich dafür zwei Ursachen unterscheiden. Ich nenne sie Implementierungsabhängig und unabhängig von der Implementierung .
Der eine Fall, der überhaupt nicht von Ihrer Umgebung abhängt ist die der statischen Objekte in C++, die hier erwähnt wurde. Der folgende Code stirbt vor main()
:
#include <iostream>
class Useless {
public:
Useless() { throw "You can't construct me!"; }
};
static Useless object;
int main() {
std::cout << "This will never be printed" << std::endl;
return 0;
}
Noch interessanter sind die plattformabhängige Ursachen . Einige wurden hier erwähnt. Eine, die hier ein paar Mal erwähnt wurde, war die Verwendung von dynamisch verknüpften Bibliotheken (DLLs in Windows, SOs in Linux, usw.) - wenn der Lader Ihres Betriebssystems sie lädt, bevor main()
können sie dazu führen, dass Ihre Anwendung vor dem main()
.
Eine allgemeinere Version dieser Sache ist das Reden über alle Dinge, die den Einstiegspunkt für Ihr Binärprogramm tut, bevor sie Ihr Einstiegspunkt( main()
). Wenn Sie Ihre Binärdatei erstellen, gibt es normalerweise einen ziemlich großen Codeblock, der aufgerufen wird, wenn der Lader Ihres Betriebssystems beginnt, Ihre Binärdatei auszuführen, und wenn er fertig ist, ruft er Ihre main()
. Eine häufige Aufgabe dieses Codes ist die Initialisierung der C/C++-Standardbibliothek. Dieser Code kann aus verschiedenen Gründen fehlschlagen (z. B. wegen eines Mangels an Systemressourcen, die er zuzuweisen versucht).
Eine interessante Möglichkeit für eine Binärdatei, Code auszuführen, bevor main()
unter Windows ist die Verwendung von TLS-Callbacks (Google wird Ihnen mehr darüber verraten). Diese Technik findet sich normalerweise in Malware als grundlegender Anti-Debugging-Trick (dieser Trick täuschte damals ollydbg, ich weiß nicht, ob er immer noch funktioniert).
Der Punkt ist, dass Ihre Frage eigentlich gleichbedeutend ist mit "gibt es eine Möglichkeit, dass das Laden einer Binärdatei dazu führt, dass der Benutzercode vor dem Code in main()
?", und die Antwort lautet Verdammt, ja!
Jedes Programm, das sich darauf verlässt, dass gemeinsam genutzte Objekte (DLLs) vor main geladen werden, kann vor main fehlschlagen.
Unter Linux wird der Code in der dynamischen Linker-Bibliothek (ld-*.so) ausgeführt, um alle abhängigen Bibliotheken weit vor dem Hauptprogramm bereitzustellen. Wenn benötigte Bibliotheken nicht gefunden werden können, keine Zugriffsrechte haben, keine normalen Dateien sind oder ein Symbol nicht enthalten, von dem der dynamische Linker, der Ihr Programm gelinkt hat, dachte, dass es vorhanden sein sollte, als er Ihr Programm gelinkt hat, kann dies zu Fehlern führen.
Außerdem kann jede Bibliothek beim Verknüpfen einen Teil des Codes ausführen. Dies liegt vor allem daran, dass die Bibliothek möglicherweise weitere Bibliotheken verlinken oder einige Konstruktoren ausführen muss (selbst in einem C-Programm könnten die Bibliotheken C++ oder etwas anderes enthalten, das Konstroktoren verwendet). Darüber hinaus haben Standard-C-Programme bereits die stdio-DATEIEN stdin, stdout und stderr angelegt. Auf vielen Systemen können diese auch geschlossen werden. Dies impliziert, dass sie auch free()ed werden, was bedeutet, dass sie (und ihre Puffer) malloc()ed wurden, was fehlschlagen kann. Es deutet auch darauf hin, dass mit den Dateideskriptoren, die diese FILE-Strukturen repräsentieren, irgendetwas anderes gemacht wurde, was ebenfalls fehlschlagen kann.
Andere Dinge, die möglicherweise passieren könnten, wären, wenn das Betriebssystem die Einrichtung der Umgebungsvariablen und/oder der Befehlszeilenargumente, die an das Programm übergeben wurden, durcheinander bringen würde. Der Code vor main musste wahrscheinlich etwas mit diesen Daten machen, bevor er main aufrief.
Viele Dinge passieren vor dem Haupttermin. Jeder von ihnen kann auf fatale Weise versagen.
Es gibt viele Möglichkeiten.
Zunächst müssen wir verstehen, was eigentlich vor der Ausführung von main passiert:
- Laden von dynamischen Bibliotheken
- Initialisierung von Globals
- Bei einigen Compilern können einige Funktionen explizit ausgeführt werden
All dies kann auf verschiedene Weise zu einem Absturz führen:
- das übliche undefinierte Verhalten (Dereferenzierung von Null-Zeigern, Zugriff auf Speicher, den man nicht verwenden sollte...)
- eine Ausnahme ausgelöst > da es keine
catch
,terminate
aufgerufen wird und das Programm endet
Das ist natürlich sehr ärgerlich und möglicherweise schwer zu debuggen, und deshalb sollte man davon absehen, Code auszuführen, bevor main
und bevorzugen, wenn möglich, eine träge Initialisierung oder eine explizite Initialisierung innerhalb von main
.
Wenn es sich um eine DLL handelt, die versagt und die man nicht ändern kann, ist das natürlich ein großes Problem.
- See previous answers
- Weitere Antworten anzeigen