Was ist der einfachste Weg, um ein C ++ - Programm zum Absturz zu bringen?


318

Ich versuche, ein Python-Programm zu erstellen, das mit einem anderen Absturzprozess verbunden ist (das liegt nicht in meiner Hand). Leider stürzt das Programm, mit dem ich verbunden bin, nicht einmal zuverlässig ab! Ich möchte also ein schnelles C ++ - Programm erstellen, das absichtlich abstürzt, aber ich weiß nicht, wie ich das am besten und kürzesten machen kann. Weiß jemand, was ich zwischen meine:

int main() {
    crashyCodeGoesHere();
}

damit mein C ++ - Programm zuverlässig abstürzt


4
Sie können Inline-Assembly verwenden, um zu versuchen, privilegierte Anweisungen auszuführen:asm { cli; };
Nate Koppenhaver

@aitchnyu Ich denke, es gibt einen Unterschied in der Verwendbarkeit der Antworten auf jede Frage. (Zu Ihrer Information: Ich habe für keine der beiden Fragen etwas gewählt)
Andrew Barber

Irgendein Kommentar zum Auslösen einer Ausnahme, während man bereits propagiert? plz chk meine Antwort unten anc Kommentar
Abhinav

4
Redis verwendet den folgenden *((char*)-1) = 'x';Code, um einen Absturz auszulösen, um mehr in meiner Antwort hier
Shafik Yaghmour

Ich fand diese Frage auf der Suche nach einem Testfall für ein Absturzmeldesystem. Ich musste während der normalen Laufzeit einen Absturz erzwingen, um den Absturzberichter und das Stack-Dump-Senden aufzurufen. Vielen Dank!
Cory Trese

Antworten:


264

Die abort()Funktion ist wahrscheinlich die beste Wahl. Es ist Teil der C-Standardbibliothek und wird als "Verursachen einer abnormalen Programmbeendigung" definiert (z. B. ein schwerwiegender Fehler oder Absturz).


14
Beachten Sie, dass ein Absturz abort()keine Destruktoren oder atexitFunktionen aufruft, obwohl dies hier wahrscheinlich keine Rolle spielt.
Xeo

139
@Xeo: Wenn es Destruktoren und atexits aufrufen würde, wäre es jetzt kein Absturz, oder?
Donal Fellows

Da abort()die richtige Antwort ist, sollte 'exit (-1); `akzeptabel sein?
Asir6

9
Nein, da es keinen Absturz verursacht, wird lediglich berichtet, dass etwas nicht getan werden konnte.
Bootscodierer

Windows. GCC-5.4.0. Beendigungscode: 3. Keine Fehlermeldung. Konsolenmeldung: "Diese Anwendung hat die Runtime aufgefordert, sie auf ungewöhnliche Weise zu beenden. Weitere Informationen erhalten Sie vom Support-Team der Anwendung."
Vadzim

113

Versuchen:

raise(SIGSEGV);  // simulates a standard crash when access invalid memory
                 // ie anything that can go wrong with pointers.

Gefunden in:

#include <signal.h>

3
Es ist mehr als nur implementierungsdefiniert - das Signal kann abgefangen werden signal(). Die meisten vernünftigen Anwendungen tun dies jedoch nicht.
Abenddämmerung -inaktiv-

12
Es stürzt genauso ab wie ein normales SIGSEGV innerhalb der Anwendung (so stürzen die meisten Anwendungen ab). Es ist genau definiert, was es tut (standardmäßig beendet es die Anwendung und generiert eine Kerndatei). Ja, Sie können einen Handler einstellen, aber wenn Sie einen haben, möchten Sie das nicht auf die gleiche Weise testen !!
Martin York

1
+1 für raise(). Auf diese Weise können Sie eine Vielzahl verschiedener Arten von Ausnahmen testen, indem Sie einfach das Argument ändern.

3
Lieblingslösung, ist jedoch plattformabhängig.
Nadim Farhat

@ NadimFarhat: Auf welche Weise. Ein Signal ist ein Signal auf allen Plattformen.
Martin York

74

Durch Teilen durch Null stürzt die Anwendung ab:

int main()
{
    return 1 / 0;
}

29
Je nachdem, wie clever Ihr Compiler ist, wird dies beim Kompilieren abgefangen. Ich weiß, dass Visual Studio 2008 dies nicht für C ++ oder C # kompiliert.
AidanO

2
Ich habe es kompiliert und ausgeführt. Soll ich Ihnen die EXE-Datei schleifen?
Roee Gavirel

1
In der Release-Konfiguration in Visual Studio-Versionen wie 2010 wird es problemlos ausgeführt. Ich denke, es ist eine Optimierung.
Tededyyu

2
iirc es stürzt nicht auf Arm
Sherpya

2
Dies ist ein undefiniertes Verhalten und es ist nicht garantiert, dass es abstürzt. Oft nehmen Compiler an, dass undefiniertes Verhalten nicht erreichbar ist. Dies kann dazu führen, dass der mainTextkörper einschließlich der retAnweisung vollständig gelöscht wird . Die Ausführung fällt möglicherweise in die folgende Funktion.
usr

64
*((unsigned int*)0) = 0xDEAD;

54
Es ist nicht garantiert, dass dies abstürzt.
Windows-Programmierer

8
@Windowsprogrammer: nein, es ist nicht garantiert . Aber welche sane OS nicht stoppen eine Anwendung , die versucht, zuzugreifen Speicher bei der Adresse 0?
Joachim Sauer

29
"Aber welches vernünftige Betriebssystem stoppt eine Anwendung nicht, die versucht, unter der Adresse 0 auf den Speicher zuzugreifen?" - Das wollen Sie eigentlich nicht fragen, aber ich werde trotzdem antworten. In einigen Computern befindet sich RAM an der Adresse 0, und es ist für ein Programm von großer Bedeutung, dort einen Wert zu speichern. Eine aussagekräftigere Frage wäre: "Welches Betriebssystem stoppt eine Anwendung, die auf den Speicher zugreift, nicht an der Adresse, die eine C ++ - Implementierung für einen Nullzeiger reserviert hat?" In diesem Fall kenne ich keine. Im ursprünglichen Programm geht es jedoch um die C ++ - Sprache, nicht um Betriebssysteme.
Windows-Programmierer

6
Sein undefiniertes Verhalten. Es ist vollkommen in Ordnung, nichts zu tun. Eine Maschine, die nicht abstürzt: Alles, auf dem ein Prozessor der Z80-Serie läuft (ich nehme an (mein Z80a macht nichts)).
Martin York

28
Obwohl dies nicht garantiert abstürzt, ist es eine der häufigsten Arten von Abstürzen in C ++. Wenn Sie also einen Absturz simulieren möchten, ist dies eine "authentische" Methode :)
Chris Burt-Brown

53

Nun sind wir auf Stack - Überlauf , oder nicht?

for (long long int i = 0; ++i; (&i)[i] = i);

(Es ist nicht garantiert, dass es nach irgendwelchen Maßstäben abstürzt, aber es gibt auch keine der vorgeschlagenen Antworten, einschließlich der akzeptierten, da SIGABRTes ohnehin hätte abgefangen werden können. In der Praxis wird dies überall abstürzen.)


4
Ich kann sehen, dass das auf einem System mit nicht geschützten Codepages lustig ist und Sie Ihr Programm mit einem Code überschreiben, der versehentlich eine Endlosschleife ist, die nichts tut. Sehr hoch sehr hoch höchst unwahrscheinlich, aber möglicherweise möglich.
Martin York

@Loki: Was ist, wenn es nur aus jedem 4000. Byte liest? Wäre es weniger wahrscheinlich, dass das abstürzt? Auf jeden Fall weniger gefährlich.
Mooing Duck

70
Dieser Absturzalgorithmus ist nicht O (1)!
Anton Barkovsky

@MooingDuck: Ich mache nur einen lustigen Kommentar. Nimm es nicht so ernst :-) Aber es wäre interessant, wenn jemand eine Folge von Anweisungen finden würde, die etwas Lustiges bewirken.
Martin York

1
@LokiAstari: Du hast absolut recht. Ich habe (&i)[i] += !istattdessen darüber nachgedacht , aber ich befürchtete, der Compiler könnte klug genug sein und das optimieren. :-)
Sam Hocevar

35
 throw 42;

Nur die Antwort ... :)


1
Windows. GCC-5.4.0. Beendigungscode: 3. Keine Fehlermeldung. Konsolenmeldung: "Beenden wird aufgerufen, nachdem eine Instanz von 'int' ausgelöst wurde. Diese Anwendung hat die Runtime aufgefordert, sie auf ungewöhnliche Weise zu beenden. Weitere Informationen erhalten Sie vom Support-Team der Anwendung."
Vadzim

15

assert(false); ist auch ziemlich gut.

Gemäß ISO / IEC 9899: 1999 ist ein Absturz garantiert, wenn NDEBUG nicht definiert ist:

Wenn NDEBUG [...] definiert ist, wird das Assert-Makro einfach als definiert

#define assert(ignore) ((void)0)

Das Assert-Makro wird jedes Mal, wenn es enthalten ist, entsprechend dem aktuellen Status von NDEBUG neu definiert.

[...]

Das Assert-Makro fügt Diagnosetests in Programme ein. [...] wenn der Ausdruck (der einen Skalartyp haben soll) falsch ist [...]. Es ruft dann die Abbruchfunktion auf.


Ich erinnere mich vage, wie sich VC 2005 zwischen Debug und Release mit Asserts anders verhält.
Tom Kerr

8
@Tom assertentspricht dem ((void)0)Release-Modus.
Seth Carnegie

2
@SethCarnegie Sehen Sie nicht, was daran falsch ist - nur wenn der definierte NDEBUG-definierte Wille nicht abstürzt? Dans Antwort war meiner Meinung nach ziemlich fair.
Adrian Cornish

@AdrianCornish Ich habe nur Tom Kerrs Frage beantwortet und nicht gesagt, dass diese Antwort falsch ist. Ich habe diese Antwort nicht abgelehnt.
Seth Carnegie

3
Ich weiß nicht, warum er diesen Testcode "veröffentlichen" würde.
Joel B

11

Da ein Absturz ein Symptom für das Aufrufen von undefiniertem Verhalten ist und das Aufrufen von undefiniertem Verhalten zu allem führen kann, einschließlich eines Absturzes, denke ich nicht, dass Sie Ihr Programm wirklich zum Absturz bringen möchten, sondern es einfach in einen Debugger fallen lassen möchten. Der tragbarste Weg, dies zu tun, ist wahrscheinlich abort().

Während raise(SIGABRT)es den gleichen Effekt hat, ist es sicherlich mehr zu schreiben. Beide Möglichkeiten können jedoch durch Installieren eines Signalhandlers für abgefangen werden SIGABRT. Abhängig von Ihrer Situation möchten / müssen Sie möglicherweise ein anderes Signal auslösen. SIGFPE, SIGILL, SIGINT, SIGTERMOder SIGSEGVkönnte der Weg zu gehen, aber sie alle abgefangen werden können.

Wenn Sie nicht portierbar sind, sind Ihre Auswahlmöglichkeiten möglicherweise noch umfangreicher, z. B. unter SIGBUSLinux.


1
Ich bezweifle wirklich, dass er einen Debugger haben will. Er scheint testen zu wollen, was passiert, wenn der Aufrufer eines abstürzenden Programms einen Absturz erhält. Welches ist sehr vernünftig.
Donal Fellows

9

Der einzige Blitz, den ich hatte, ist die Funktion abort () :

Es bricht den Prozess mit einer abnormalen Programmbeendigung ab. Es erzeugt das SIGABRT-Signal , das standardmäßig dazu führt, dass das Programm beendet wird und ein nicht erfolgreicher Beendigungsfehlercode an die Host-Umgebung zurückgegeben wird. Das Programm wird beendet, ohne Destruktoren für Objekte mit automatischer oder statischer Speicherdauer auszuführen und ohne Aufrufen einer Funktion atexit (die von exit () aufgerufen wird, bevor das Programm beendet wird). Es kehrt nie zu seinem Anrufer zurück.


9

Die Antwort ist plattformspezifisch und hängt von Ihren Zielen ab. Aber hier ist die Mozilla Javascript-Absturzfunktion, die meiner Meinung nach viele Herausforderungen für diese Funktion veranschaulicht:

static JS_NEVER_INLINE void
CrashInJS()
{
    /*
     * We write 123 here so that the machine code for this function is
     * unique. Otherwise the linker, trying to be smart, might use the
     * same code for CrashInJS and for some other function. That
     * messes up the signature in minidumps.
     */

#if defined(WIN32)
    /*
     * We used to call DebugBreak() on Windows, but amazingly, it causes
     * the MSVS 2010 debugger not to be able to recover a call stack.
     */
    *((int *) NULL) = 123;
    exit(3);
#elif defined(__APPLE__)
    /*
     * On Mac OS X, Breakpad ignores signals. Only real Mach exceptions are
     * trapped.
     */
    *((int *) NULL) = 123;  /* To continue from here in GDB: "return" then "continue". */
    raise(SIGABRT);  /* In case above statement gets nixed by the optimizer. */
#else
    raise(SIGABRT);  /* To continue from here in GDB: "signal 0". */
#endif
}

2
Sie sollten das komplett fallen lassen und stattdessen jQuery verwenden.
Thomas Weller

1
Dies ist ein undefiniertes Verhalten und es ist nicht garantiert, dass es abstürzt. Oft nehmen Compiler an, dass undefiniertes Verhalten nicht erreichbar ist. In diesem Fall wird zumindest die abstürzende Zeile gelöscht, und möglicherweise auch anderer Code.
Usr

8

Ich sehe, dass hier viele Antworten veröffentlicht werden, die in glückliche Fälle geraten, um die Arbeit zu erledigen, aber keine von ihnen ist zu 100% deterministisch für einen Absturz. Einige stürzen auf einer Hardware und einem Betriebssystem ab, andere nicht. Es gibt jedoch eine Standardmethode gemäß dem offiziellen C ++ - Standard, um einen Absturz zu verursachen.

Zitat aus C ++ Standard ISO / IEC 14882 §15.1-7 :

Wenn der Mechanismus zur Ausnahmebehandlung nach Abschluss der Initialisierung des Ausnahmeobjekts, jedoch vor der Aktivierung eines Handlers für die Ausnahme, eine Funktion aufruft, die über eine Ausnahme beendet wird, wird std :: terminate aufgerufen (15.5.1).

struct C {
    C() { }
    C(const C&) {
        if (std::uncaught_exceptions()) {
            throw 0; // throw during copy to handler’s exception-declaration object (15.3)
        }
    }
};
int main() {
    try {
    throw C(); // calls std::terminate() if construction of the handler’s
    // exception-declaration object is not elided (12.8)
    } catch(C) { }
}

Ich habe einen kleinen Code geschrieben, um dies zu demonstrieren, und kann hier auf Ideone gefunden und ausprobiert werden .

class MyClass{
    public:
    ~MyClass() throw(int) { throw 0;}
};

int main() {
  try {
    MyClass myobj; // its destructor will cause an exception

    // This is another exception along with exception due to destructor of myobj and will cause app to terminate
     throw 1;      // It could be some function call which can result in exception.
  }
  catch(...)
  {
    std::cout<<"Exception catched"<<endl;
  }
  return 0;
}

ISO / IEC 14882 §15.1 / 9 erwähnt den Wurf ohne Try-Block, was zu einem impliziten Aufruf zum Abbruch führt:

Wenn derzeit keine Ausnahme behandelt wird, ruft das Ausführen eines Wurfausdrucks ohne Operanden std :: terminate () auf.

Andere schließen ein: vom Zerstörer werfen: ISO / IEC 14882 §15.2 / 3


7
*( ( char* ) NULL ) = 0;

Dies führt zu einem Segmentierungsfehler.


10
Es ist nicht garantiert, dass dies abstürzt.
Windows-Programmierer

23
"Was wird stattdessen passieren?" - Stattdessen könnte alles passieren. Das Verhalten ist undefiniert, daher kann die Implementierung einer der Variablen Ihres Programms 0 zuweisen oder einer der Variablen Ihres Programms 42 zuweisen oder Ihre Festplatte formatieren und die Ausführung Ihres Programms fortsetzen.
Windows-Programmierer

7
(Fortsetzung der Einstellung "Windows-Programmierer") Es kann dazu führen, dass Ihr Computer explodiert, oder dass er zum Leben erweckt wird und die Menschheit übernimmt. oder ... es wird in 99,9% abstürzen und es wird als "undefiniertes Verhalten" definiert, weil niemand die Verantwortung dafür übernehmen will.
Roee Gavirel

1
Tatsächlich ist nicht garantiert, dass dies auch nur undefiniertes Verhalten bewirkt - es könnte vollständig definiert sein und ordnungsgemäß funktionieren. Betrachten Sie diesen Code: pastebin.com/WXCtTiDD (Unter Linux als Root getestet, können Sie dies auch als Nicht-Root-Benutzer tun, wenn Sie einige Konfigurationsänderungen vornehmen. Wiki.debian.org/mmap_min_addr )
cha0site

2
@ cha0site: Der Standard garantiert ein undefiniertes Verhalten, da dadurch ein Nullzeiger dereferenziert wird. Welches Verhalten Sie auch unter Linux beobachtet haben, es ist unter dem Dach des "undefinierten Verhaltens" zulässig
Ben Voigt

6

Dieser fehlt:

int main = 42;

1
Ja tut es; Aber es macht etwas Spektakuläres, wenn Sie es ausführen.
Joshua

5

Was ist mit einem Stapelüberlauf durch einen rekursiven Methodenaufruf in einer toten Schleife?

#include <windows.h>
#include <stdio.h>

void main()
{
    StackOverflow(0);
}

void StackOverflow(int depth)
{
    char blockdata[10000];
    printf("Overflow: %d\n", depth);
    StackOverflow(depth+1);
}

Siehe Originalbeispiel in Microsoft KB


4
Was würde einen ausreichend intelligenten Compiler daran hindern, sowohl die nicht verwendete Stapelzuordnung als auch den Endaufruf zu optimieren?
JB.

@JB: Leider habe ich keine Ahnung, weil ich nicht mit der vorhandenen Compiler-Optimierungslogik
vertraut bin

8
Nun, hier kompiliert mit gcc 4.6.0 bei Optimierungsstufen -O2 und höher, optimiert es einwandfrei. Zum Segfault wird -O1 oder niedriger benötigt.
JB.

@Abhinav: Poste einfach deine Antwort mit all diesen Möglichkeiten, die als Beispiele in C ++ ausgedrückt werden :)
sll

5

Dies stürzt auf meinem Linux-System ab, da Zeichenfolgenliterale im Nur-Lese-Speicher gespeichert sind:

0[""]--;

G ++ weigert sich übrigens, dies zu kompilieren. Compiler werden immer schlauer :)


4
int i = 1 / 0;

Ihr Compiler wird Sie wahrscheinlich davor warnen, aber unter GCC 4.4.3 wird er problemlos kompiliert. Dies führt wahrscheinlich zu einem SIGFPE (Gleitkomma-Ausnahme), das in einer realen Anwendung möglicherweise nicht so wahrscheinlich ist wie SIGSEGV (Speichersegmentierungsverletzung) wie Die anderen Antworten verursachen, aber es ist immer noch ein Absturz. Meiner Meinung nach ist dies viel besser lesbar.

Ein anderer Weg, wenn wir betrügen und benutzen wollen signal.h, ist:

#include <signal.h>
int main() {
    raise(SIGKILL);
}

Dies ist im Gegensatz zu SIGSEGV garantiert, um den Unterprozess abzubrechen.


2
Es ist nicht garantiert, dass dies abstürzt.
Windows-Programmierer

11
Die C ++ - Sprache garantiert nicht, dass 1/0 ein SIGFPE verursacht. Verhalten ist undefiniert. Die Implementierung könnte sagen, das Ergebnis ist 42.
Windows-Programmierer

1
Wenn das Verhalten nicht definiert ist, kann die Implementierung tun, was sie will. Die C ++ - Sprache verhindert oder erfordert keine Implementierung zum Schreiben eines Absturzabbaus, die C ++ - Sprache verhindert oder erfordert keine Implementierung zum Zuweisen von 42 usw.
Windows-Programmierer

2
@Giorgio Wenn die Hardware nicht in der Lage ist, sie automatisch abzufangen, zwingen Sie die Compiler dennoch, mindestens zwei Anweisungen auszugeben, von denen eine auch eine Verzweigung wäre. Das ist ungefähr die Verdoppelung der Kosten einer Division. Jeder zahlt diese Kosten so. Wenn es optional ist und Sie es möchten, können Sie immer noch eine Bibliotheksfunktion dafür verwenden. Wenn es nicht optional ist und Sie es nicht wollen, würden Sie trotzdem die Kosten bezahlen.
Flexo

2
@Giorgio: Ich habe eine Anwendung, die 100.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000. Ich weiß, dass 0 davon eine Division durch Null sein wird, obwohl der Compiler dies auf keinen Fall wissen kann. Ich möchte definitiv nicht, dass der Compiler den Scheck für eine Division durch Null setzt.
Martin York

4

Dies ist eine garantiertere Version des Abbruchs, die in den obigen Antworten dargestellt ist. Sie kümmert sich um die Situation, in der Sigabrt blockiert ist. Sie können jedes Signal anstelle des Abbruchs verwenden, bei dem das Programm standardmäßig abstürzt.

#include<stdio.h>
#include<signal.h>
#include<unistd.h> 
#include<stdlib.h>
int main()
{
    sigset_t act;
    sigemptyset(&act);
    sigfillset(&act);
    sigprocmask(SIG_UNBLOCK,&act,NULL);
    abort();
}

3
int* p=0;
*p=0;

Dies sollte auch abstürzen. Unter Windows stürzt es mit AccessViolation ab und sollte auf allen Betriebssystemen, denke ich, dasselbe tun.


5
on all OS-esNein, es ist nicht in nicht geschütztem OS nicht abstürzen (zB MS-DOS.) Eigentlich manchmal ist etwas in der Adresse 0! Für den x86-Real-Modus befindet sich die Interrupt-
Vektortabelle

Es ist nicht auf Irix abgestürzt. Mir wurde leider klar, als wir diesen Code auf Linux portierten (wo wir ihn nicht einmal erreichten) main().
Scheff

3

Dies ist das von Google in Breakpad bereitgestellte Snippet.

  volatile int* a = reinterpret_cast<volatile int*>(NULL);
  *a = 1;

1
Da ich Breakpad teste, ist dies genau das, was ich wollte! Ich habe festgestellt, dass einige Breakpad-Minidumps keine Stapelverfolgung erzeugen, die auf die Zeile in meinem Code zeigt, die den Absturz verursacht. Dieser tut es, also kann ich ihn als guten Poc-Test verwenden.
BuvinJ

2
int main(int argc, char *argv[])
{
    char *buf=NULL;buf[0]=0;
    return 0;
}

2

Obwohl diese Frage bereits eine akzeptierte Antwort hat ...

void main(){
    throw 1;
}

Oder... void main(){throw 1;}


2

Das Schreiben in einen Nur-Lese-Speicher führt zu einem Segmentierungsfehler, es sei denn, Ihr System unterstützt keine Nur-Lese-Speicherblöcke.

int main() {
    (int&)main = 0;
}

Ich habe es mit MingGW 5.3.0 unter Windows 7 und GCC unter Linux Mint getestet. Ich nehme an, dass andere Compiler und Systeme einen ähnlichen Effekt erzielen.


1

Oder anders, seit wir auf dem Bandwagen sind.

Ein schönes Stück unendlicher Rekursion. Garantiert, um Ihren Stapel zu sprengen.

int main(int argv, char* argc)
{
   return main(argv, argc)
}

Druckt aus:

Segmentierungsfehler (Core Dumped)


13
Der Aufruf mainselbst ist eigentlich nicht definiertes Verhalten, falls Sie nicht wissen :) Auch Endrekursion ist nicht garantiert , um Ihren Stapel zu blasen. Wenn Sie eine "Garantie" wünschen, müssen Sie nach dem rekursiven Aufruf etwas tun , sonst könnte der Compiler die Rekursion in eine Endlosschleife optimieren.
Fredoverflow

0

Eine, die noch nicht erwähnt wurde:

((void(*)())0)();

Dadurch wird der Nullzeiger als Funktionszeiger behandelt und dann aufgerufen. Wie bei den meisten Methoden kann nicht garantiert werden, dass das Programm abstürzt, aber die Wahrscheinlichkeit, dass das Betriebssystem dies deaktiviert und das Programm jemals zurückkehrt, ist vernachlässigbar gering.


3
Ich kenne mehrere Computer, die einen Neustart verursachen, da der Startcode des Betriebssystems effektiv der Adresse 0 zugeordnet ist. Gehen Sie nicht davon aus, dass alles wie Ihr PC funktioniert. Man könnte sagen, dass dies ein Absturz war, aber es ist nicht sehr nützlich, da Sie es nicht debuggen können, da der gesamte Status beim Start gelöscht wird.
Martin York

@Loki Astari: Ich werde trotzdem sagen, dass dies ein Absturz ist - wenn dies dazu führen kann, kann das zu debuggende Programm auch so sein, was bedeutet, dass es ein ebenso guter Test ist wie jeder andere. Andererseits bin ich gespannt, auf welchen dieser Maschinen Python ausgeführt werden kann.
Anton Golov

Ich denke, Sie haben den Punkt verpasst. Ich habe OS-Code bei 0 gesehen. Das bedeutet nicht, dass es keine Systeme mit normalem gutem Code gibt, die bei 0 einwandfrei funktionieren. Oder die Bytes bei 0 könnten genauso gut der Opcode für die Rückgabe sein.
Martin York

Mir ist der OS-Code bei 0 bekannt. Das ist einer der Gründe, warum ich stark bezweifle, dass die Bytes bei 0 der Opcode für die Rückgabe sind. Das Programm wird ganz klar nicht mehr ausgeführt und nicht auf die übliche Weise beendet, dh es ist abgestürzt - wenn dies für den Fragesteller nicht gut genug ist, erwarte ich, dass er es selbst kommentiert.
Anton Golov

2
Sie kennen nur den Betriebssystemcode für Ihren Computer. Ich versuche zu sagen, dass es für Sie scheitern kann. Das heißt aber nichts. Es gibt viele Systeme da draußen. Ich bin sicher, dass einige von ihnen dies funktionieren können (dh wie nicht abstürzen). Sich auf maschinen- / betriebssystemspezifisches Verhalten zu verlassen, ist eine schlechte Idee und verursacht auf lange Sicht Wartungsprobleme. Die Idee der Site ist es, guten Code zu fördern (nicht nur Code, der so funktioniert).
Martin York

0
void main()
{

  int *aNumber = (int*) malloc(sizeof(int));
  int j = 10;
  for(int i = 2; i <= j; ++i)
  {
      aNumber = (int*) realloc(aNumber, sizeof(int) * i);
      j += 10;
  }

}

Hoffe das stürzt ab. Prost.


0
int main()
{
    int *p=3;
    int s;
    while(1) {
        s=*p;
        p++;
    }
}

2
Es wäre toll, eine Klarstellung zu haben :)
Olyv

1
Der p-Zeiger geht über den Adressraum des Programms hinaus, was ein Speicherfehler ist, da ein Prozess nicht auf den Speicher eines anderen Prozesses zugreifen kann. Dies führt zum Absturz des Programms. Der Zeiger p zeigt auf eine zufällige Stelle in seinem Adressraum. Wenn er irgendwann unendlich inkrementiert und dereferenziert wird, zeigt er auf den (Prozess-) Adressraum eines anderen Programms. so wird es nach einiger Zeit abstürzen.
sc_cs

Oder hypothetisch könnte es einen ganzzahligen Überlauf erreichen und unendlich laufen. Ich würde versuchen, long longoder zu verwenden size_tund mit pdem jeweiligen Maximalwert oder in der Nähe davon zu beginnen, um schneller abzustürzen. Obwohl es auch in diesem Fall nicht garantiert ist, dass es abstürzt.
Patrick Roberts

0

Eine stilvolle Möglichkeit hierfür ist ein rein virtueller Funktionsaufruf:

class Base;

void func(Base*);

class Base
{
public:
   virtual void f() = 0;
   Base() 
   {
       func(this);
   }
};

class Derived : Base
{
   virtual void f()
   {
   }
};

void func(Base* p)
{
   p->f();
}


int main()
{
    Derived  d;
}

Zusammengestellt mit gcc, druckt dies:

reine virtuelle Methode aufgerufen

Beenden ohne aktive Ausnahme beendet

Abgebrochen (Core Dumped)


0

Sie können Assembly in Ihrem C ++ verwenden, code ABER INT 3 nur für x86-Systeme. Andere Systeme verfügen möglicherweise über andere Trap- / Breakpoint-Anweisungen.

int main()
{
    __asm int 3;

    return 0;
}

INT 3 verursacht einen Interrupt und ruft einen vom Betriebssystem eingerichteten Interrupt-Vektor auf.


0

Verwenden Sie __builtin_trap () in GCC oder clang oder __debugbreak () in MSVC. Wenn diese Haltepunkte / Traps nicht behandelt werden, führt dies zu einer nicht behandelten Haltepunktausnahme / einem Absturz. Andere Vorschläge, die abort () oder exit () verwenden: Diese können von anderen Threads verarbeitet werden, wodurch es schwieriger wird, den Stapel des Threads zu sehen, der den Absturz verbreitet hat.


-2
char*freeThis;
free(freeThis);

Das Freigeben eines nicht initialisierten Zeigers ist ein undefiniertes Verhalten. Auf vielen Plattformen / Compilern freeThiswird ein zufälliger Wert angezeigt (was auch immer sich zuvor an diesem Speicherort befand). Wenn Sie es freigeben, wird das System aufgefordert, den Speicher an dieser Adresse freizugeben. Dies führt normalerweise zu einem Segmentierungsfehler und führt zum Absturz des Programms.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.