Jaki jest najprostszy sposób na awarię programu C ++?

318

Próbuję stworzyć program w języku Python, który będzie współpracował z innym procesem powodującym awarie (który jest poza moim zasięgiem). Niestety program, z którym się komunikuję, nie ulega awarii nawet niezawodnie! Chcę więc stworzyć szybki program C ++, który celowo ulega awarii, ale tak naprawdę nie znam najlepszego i najkrótszego sposobu, aby to zrobić, czy ktoś wie, co umieścić między moim:

int main() {
    crashyCodeGoesHere();
}

aby niezawodnie zawiesić mój program C ++

jonathan topf
źródło
4
możesz użyć wbudowanego zestawu, aby spróbować wykonać instrukcje uprzywilejowane:asm { cli; };
Nate Koppenhaver,
@ aitchnyu Myślę, że istnieje różnica w użyteczności odpowiedzi na każde pytanie. (FYI: Nic nie głosowałem na żadne pytanie)
Andrew Barber,
jakikolwiek komentarz dotyczący zgłaszania wyjątku, gdy ktoś już się propaguje? plz chk moja odpowiedź poniżej komentarza anc
Abhinav,
4
Redis używa następującego *((char*)-1) = 'x';kodu, aby wywołać awarię w celu debugowania, przeczytaj więcej w mojej odpowiedzi tutaj
Shafik Yaghmour
Znalazłem to pytanie, szukając przypadku testowego dla systemu zgłaszania awarii. Musiałem wymusić awarię podczas normalnego działania, aby wywołać raport o awarii i wysłać zrzut stosu. Dzięki!
Cory Trese

Odpowiedzi:

264

Ta abort()funkcja jest prawdopodobnie najlepszym wyborem. Jest to część standardowej biblioteki C i jest zdefiniowana jako „powodująca nieprawidłowe zakończenie programu” (np. Błąd krytyczny lub awaria).

Duskwuff -inactive-
źródło
14
Pamiętaj, że awaria abort()nie wywołuje żadnych niszczycieli ani atexitfunkcji, choć prawdopodobnie nie będzie to miało znaczenia.
Xeo,
139
@Xeo: Gdyby wywołał destruktory is atexit, nie byłoby teraz awarii, prawda?
Donal Fellows,
Ponieważ odpowiedź abort()jest prawidłowa, należy „wyjść (-1);„ być do przyjęcia?
asir6,
9
Nie, ponieważ nie powoduje awarii, po prostu informuje, że czegoś nie można zrobić.
Boatcoder
Windows GCC-5.4.0. Kod zakończenia: 3. Brak komunikatu o błędzie. Komunikat konsoli: „Ta aplikacja poprosiła środowisko wykonawcze o jej zakończenie w nietypowy sposób. Skontaktuj się z zespołem pomocy technicznej aplikacji, aby uzyskać więcej informacji.”.
Vadzim
113

Próbować:

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

Znaleziono w:

#include <signal.h>
Martin York
źródło
3
To coś więcej niż tylko zdefiniowanie implementacji - sygnał może zostać złapany signal(). Jednak większość rozsądnych aplikacji tego nie robi.
duskwuff -inactive-
12
Awaria nastąpi dokładnie w taki sam sposób, jak normalny SIGSEGV w aplikacji (co powoduje awarie większości aplikacji). Jest dobrze zdefiniowane, co robi (domyślnie wychodzi z aplikacji i generuje plik podstawowy). Tak, możesz ustawić moduł obsługi, ale jeśli go masz, nie chcesz go testować w ten sam sposób !!
Martin York,
1
+1 dla raise(). To pozwala przetestować mnóstwo różnych rodzajów wyjątków, po prostu zmieniając argument.
3
ulubione rozwiązanie, jednak zależy ono od platformy.
Nadim Farhat
@NadimFarhat: W jaki sposób. Sygnał jest sygnałem na wszystkich platformach.
Martin York
74

Dzielenie przez zero spowoduje awarię aplikacji:

int main()
{
    return 1 / 0;
}
Roee Gavirel
źródło
29
W zależności od tego, jak sprytny jest twój kompilator, zostanie on przechwycony podczas kompilacji. Wiem, że Visual Studio 2008 nie skompiluje tego dla C ++ lub C #.
AidanO
2
Skompilowałem i uruchomiłem, czy chcesz, żebym przeszlifował Ci .exe?
Roee Gavirel
1
W konfiguracji wersji w Visual Studio najnowszych wersji, takich jak 2010, będzie działać bez problemu. Myślę, że to jakaś optymalizacja.
tedyyu
2
iirc nie zawiesza się na ramieniu
Sherpya
2
Jest to niezdefiniowane zachowanie i nie ma gwarancji awarii. Często kompilatory zakładają, że niezdefiniowane zachowanie jest nieosiągalne. Może to prowadzić do maincałkowitego usunięcia treści, w tym retinstrukcji. Wykonanie może po prostu należeć do następującej funkcji.
usr
64
*((unsigned int*)0) = 0xDEAD;
Keith Nicholas
źródło
54
Nie gwarantuje to awarii.
programista Windows
8
@Windowsprogrammer: nie, nie ma gwarancji . Ale który rozsądny system operacyjny nie zatrzymuje aplikacji, która próbuje uzyskać dostęp do pamięci pod adresem 0?
Joachim Sauer,
29
„Ale który rozsądny system operacyjny nie zatrzymuje aplikacji, która próbuje uzyskać dostęp do pamięci pod adresem 0?” - Nie o to tak naprawdę chcesz zapytać, ale i tak odpowiem. Na niektórych komputerach jest pamięć RAM pod adresem 0 i ma to dla programu duże znaczenie, aby zapisać tam wartość. Bardziej znaczącym pytaniem byłoby „Który system operacyjny nie zatrzymuje aplikacji, która uzyskuje dostęp do pamięci pod adresem zarezerwowanym przez implementację C ++ dla wskaźnika zerowego?” W takim razie nic nie wiem. Ale oryginalny program dotyczy języka C ++, a nie systemów operacyjnych.
programista Windows
6
Jego nieokreślone zachowanie. Nic nie szkodzi. Maszyna, która się nie zawiesi: Wszystko, co działa na procesorze z serii Z80 (zakładam (mój Z80a nic nie robi)).
Martin York,
28
Chociaż nie gwarantuje to awarii, jest to jeden z najczęstszych rodzajów awarii w C ++. Więc jeśli chcesz zasymulować awarię, jest to „autentyczny” sposób, aby to zrobić :)
Chris Burt-Brown,
53

Cóż, jesteśmy na przepełnieniu stosu , czy nie?

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

(Nie ma gwarancji SIGABRT, że nastąpi awaria według jakichkolwiek standardów, ale nie ma też żadnej z sugerowanych odpowiedzi, w tym tej zaakceptowanej, ponieważ i tak można ją złapać. W praktyce nastąpi awaria wszędzie).

sam hocevar
źródło
4
Widzę, że to zabawne w systemie z niezabezpieczonymi stronami kodowymi i zastępujesz swój program jakimś kodem, który przypadkowo jest nieskończoną pętlą, która nic nie robi. Wysoce wysoce wysoce wysoce mało prawdopodobne, ale potencjalnie możliwe.
Martin York,
@Loki: Co, jeśli po prostu czyta z każdego 4000 bajtu? Czy mniej prawdopodobne byłoby awarie? Zdecydowanie mniej niebezpieczne.
Mooing Duck,
70
Ten algorytm awarii nie jest O (1)!
Anton Barkovsky,
@MooingDuck: Właśnie robię zabawny komentarz. Nie bierz tego tak poważnie :-) Ale byłoby interesujące, gdyby ktoś znalazł sekwencję instrukcji, która zrobiła coś śmiesznego.
Martin York,
1
@LokiAstari: masz absolutną rację. Zastanawiałem się nad tym (&i)[i] += !i, ale obawiałem się, że kompilator może być wystarczająco sprytny i chce to zoptymalizować. :-)
sam hocevar,
35
 throw 42;

Tylko odpowiedź ... :)

Macke
źródło
1
Windows GCC-5.4.0. Kod zakończenia: 3. Brak komunikatu o błędzie. Komunikat konsoli: „zakończenie wywoływane po zgłoszeniu wystąpienia„ int ”Ta aplikacja poprosiła środowisko wykonawcze o zakończenie go w nietypowy sposób. Skontaktuj się z zespołem pomocy technicznej aplikacji, aby uzyskać więcej informacji.”.
Vadzim
15

assert(false); też jest całkiem niezły.

Zgodnie z ISO / IEC 9899: 1999 gwarantuje się awarię, gdy NDEBUG nie jest zdefiniowany:

Jeśli zdefiniowano NDEBUG [...], makro assert definiuje się po prostu jako

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

Makro assert jest redefiniowane zgodnie z bieżącym stanem NDEBUG za każdym razem, gdy jest dołączane.

[...]

Makro assert umieszcza testy diagnostyczne w programach; [...] jeśli wyrażenie (które powinno mieć typ skalarny) jest fałszywe [...]. Następnie wywołuje funkcję przerwania.

Dan F.
źródło
Nie pamiętam, jak VC 2005 zachowywał się inaczej między debugowaniem a wydaniem z zapewnieniami?
Tom Kerr,
8
@Tom assertjest równoważny ((void)0)w trybie zwolnienia.
Seth Carnegie,
2
@SethCarnegie Nie widzisz, co w tym złego - tylko jeśli zdefiniowana definicja NDEBUG nie ulegnie awarii? Odpowiedź Dansa była dość uczciwa IMHO.
Adrian Cornish,
@AdrianCornish Odpowiadałem tylko na pytanie Toma Kerr, nie twierdząc, że ta odpowiedź była zła. Nie głosowałem za tą odpowiedzią.
Seth Carnegie,
3
Nie wiem, dlaczego zrobiłby kompilację tego kodu testowego.
Joel B,
11

Ponieważ awaria jest objawem wywoływania nieokreślonego zachowania, a ponieważ wywoływanie niezdefiniowanego zachowania może prowadzić do czegokolwiek, w tym awarii, nie sądzę, że chcesz naprawdę zawiesić swój program, ale po prostu upuść go w debuggerze. Najbardziej przenośnym sposobem na to jest prawdopodobnie abort().

Chociaż raise(SIGABRT)ma ten sam efekt, na pewno jest więcej do napisania. Oba sposoby można jednak przechwycić, instalując moduł obsługi sygnału dla SIGABRT. Więc w zależności od twojej sytuacji, możesz chcieć / potrzebować podnieść inny sygnał. SIGFPE, SIGILL, SIGINT, SIGTERMLub SIGSEGVmoże być droga, ale wszystkie mogą zostać przechwycone.

Gdy możesz być nie do przeniesienia, twoje wybory mogą być jeszcze szersze, jak SIGBUSna przykład na Linuksie.

Plazma
źródło
1
Naprawdę wątpię, czy chce zaangażować debuggera. Wygląda na to, że chce przetestować, co się stanie, gdy program wywołujący awarię dostanie awarię. Co jest bardzo rozsądne.
Donal Fellows,
9

Jedyny flash, jaki miałem to funkcja abort () :

Przerywa proces z nienormalnym zakończeniem programu, generuje sygnał SIGABRT , który domyślnie powoduje, że program przerywa zwracanie nieudanego kodu błędu zakończenia do środowiska hosta. Program zostaje zakończony bez wykonywania niszczycieli dla obiektów o automatycznym lub statycznym czasie przechowywania i bez wywoływania jakichkolwiek atexit (która jest wywoływana przez exit () przed wygaśnięciem programu) funkcja. Nigdy nie wraca do dzwoniącego.

samridhi
źródło
9

Odpowiedź zależy od platformy i zależy od twoich celów. Ale oto funkcja awarii Mozilla Javascript, która moim zdaniem ilustruje wiele wyzwań, które sprawiają, że ta funkcja działa:

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
}
Paul Biggar
źródło
2
Powinieneś całkowicie to porzucić i zamiast tego użyć jQuery.
Thomas Weller,
1
Jest to niezdefiniowane zachowanie i nie ma gwarancji awarii. Często kompilatory zakładają, że niezdefiniowane zachowanie jest nieosiągalne. W takim przypadku przynajmniej linia awaryjna zostanie usunięta, a także inny kod.
usr
8

Widzę, że opublikowano tutaj wiele odpowiedzi, które trafią w szczęśliwe przypadki, aby wykonać zadanie, ale żadna z nich nie jest w 100% deterministyczna w przypadku awarii. Niektóre ulegną awarii na jednym sprzęcie i systemie operacyjnym, inne nie. Istnieje jednak standardowy sposób, zgodnie z oficjalnym standardem C ++, aby spowodować awarię.

Cytowanie z normy C ++ ISO / IEC 14882 §15.1-7 :

Jeśli mechanizm obsługi wyjątków, po zakończeniu inicjalizacji obiektu wyjątku, ale przed aktywacją modułu obsługi wyjątku, wywołuje funkcję, która kończy działanie przez wyjątek, wywoływana jest funkcja std :: terminate (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) { }
}

Napisałem mały kod, aby to zademonstrować i można go znaleźć i wypróbować na Ideone tutaj .

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 wspomina o rzucaniu bez bloku próbnego, co powoduje niejawne wezwanie do przerwania:

Jeśli obecnie nie jest obsługiwany żaden wyjątek, wykonanie wyrażenia typu throw bez wywołań argumentów std :: terminate ()

Inne obejmują: rzut z destruktora: ISO / IEC 14882 § 15.2 / 3

Abhinav
źródło
7
*( ( char* ) NULL ) = 0;

Spowoduje to błąd segmentacji.

wrren
źródło
10
Nie gwarantuje to awarii.
programista Windows
23
„Co zamiast tego stanie się?” - Zamiast tego wszystko może się zdarzyć. Zachowanie jest niezdefiniowane, więc implementacja może przypisać 0 do jednej ze zmiennych programu lub może przypisać 42 do jednej ze zmiennych programu, lub może sformatować dysk twardy i kontynuować wykonywanie programu.
programista Windows
7
(kontynuacja myślenia „programisty Windows”) Może spowodować eksplozję komputera lub życie i przejęcie ludzkości. lub ... ulegnie awarii w 99,9% i jest zdefiniowane jako „niezdefiniowane zachowanie”, ponieważ nikt nie chce brać na siebie odpowiedzialności.
Roee Gavirel
1
W rzeczywistości nie gwarantuje to nawet niezdefiniowanego zachowania - może całkowicie zdefiniować i działać poprawnie. Rozważ ten kod: pastebin.com/WXCtTiDD (Testowany na Linuksie jako root, możesz to zrobić również jako użytkownik inny niż root, jeśli wprowadzisz jakieś zmiany w konfiguracji wiki.debian.org/mmap_min_addr )
cha0site
2
@ cha0site: Standardowo gwarantuje, że zachowanie jest niezdefiniowane, ponieważ oznacza to odwołanie wskaźnika zerowego. Jakiekolwiek zachowanie zaobserwowane w Linuksie jest dopuszczalne pod „niezdefiniowanym zachowaniem”
Ben Voigt
6

Brakuje tego:

int main = 42;
mvds
źródło
1
Tak; ale robi coś spektakularnego po uruchomieniu.
Joshua
5

Co z przepełnieniem stosu wywołaniem metody rekurencyjnej w pętli martwej?

#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);
}

Zobacz oryginalny przykład w Microsoft KB

sll
źródło
4
Co mogłoby powstrzymać wystarczająco inteligentny kompilator przed optymalizacją zarówno nieużywanego przydziału stosu, jak i wywołania końcowego?
JB.
@JB: niestety nie mam pojęcia, ponieważ nie jest zaznajomiony z istniejącą logiką optymalizacji kompilatorów
sll
8
Cóż, tutaj skompilowany z gcc 4.6.0 na poziomach optymalizacji -O2 i wyższych, optymalizuje się dobrze. Potrzebuje -O1 lub niższej do segfault.
JB.
@Abhinav: Po prostu opublikuj swoją odpowiedź, używając wszystkich tych sposobów wyrażonych jako przykłady w C ++ :)
sll 23'13
5

Występuje awaria w moim systemie Linux, ponieważ literały łańcuchowe są przechowywane w pamięci tylko do odczytu:

0[""]--;

Nawiasem mówiąc, g ++ nie chce tego skompilować. Kompilatory stają się coraz mądrzejsze :)

fredoverflow
źródło
4
int i = 1 / 0;

Twój kompilator prawdopodobnie ostrzeże Cię o tym, ale kompiluje się dobrze w GCC 4.4.3. To prawdopodobnie spowoduje SIGFPE (wyjątek zmiennoprzecinkowy), co być może nie jest tak prawdopodobne w prawdziwej aplikacji jak SIGSEGV (naruszenie segmentacji pamięci) jak inne odpowiedzi powodują, ale wciąż jest to awaria. Moim zdaniem jest to o wiele bardziej czytelne.

Innym sposobem, jeśli chcemy oszukiwać i używać signal.h, jest:

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

Gwarantuje to zabicie podprocesu, w przeciwieństwie do SIGSEGV.


źródło
2
Nie gwarantuje to awarii.
programista Windows
11
Język C ++ nie gwarantuje, że 1/0 spowoduje SIGFPE. Zachowanie jest niezdefiniowane. Implementacja może powiedzieć, że wynik to 42.
programista Windows
1
Gdy zachowanie jest niezdefiniowane, implementacja może zrobić, co chce. Język C ++ ani nie zapobiega, ani nie wymaga implementacji do napisania zrzutu awaryjnego, język C ++ nie zapobiega ani nie wymaga implementacji do przypisania 42 itd.
programista systemu Windows
2
@Giorgio, jeśli sprzęt nie ma możliwości automatycznego pułapkowania, nadal zmuszasz kompilatory do emitowania co najmniej dwóch instrukcji, z których jedna byłaby również gałęzią. To w przybliżeniu podwaja koszt podziału. Każdy płaci takie koszty. Jeśli jest opcjonalny i chcesz, zawsze możesz nadal korzystać z funkcji bibliotecznej. Jeśli nie jest to opcjonalne i nie chcesz tego, nadal musiałbyś ponieść koszty.
Flexo
2
@Giorgio: Mam aplikację, która wykonuje 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 Wiem na pewno, że 0 z nich będzie dzieleniem przez zero, chociaż nie ma możliwości, aby kompilator mógł to wiedzieć. Zdecydowanie nie chcę, aby kompilator sprawdził podział na zero.
Martin York,
4

Jest to bardziej gwarantowana wersja przerwania przedstawiona w powyższych odpowiedziach, która zajmuje się sytuacją, gdy sigabrt jest zablokowany. Możesz infact użyć dowolnego sygnału zamiast przerywania, który domyślnie powoduje zawieszenie programu.

#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();
}
bashrc
źródło
3
int* p=0;
*p=0;

To też powinno się zawiesić. W Windows zawiesza się z AccessViolation i chyba powinien działać tak samo na wszystkich systemach operacyjnych.

laci37
źródło
5
on all OS-esNie, nie ulega awarii w niezabezpieczonym systemie operacyjnym (np. MS-DOS). Właściwie czasami coś jest pod adresem 0! W trybie rzeczywistym x86 tablica wektorów przerwań znajduje się pod adresem 0.
ikh
Nie rozbił się na Irixie. Niestety zdałem sobie sprawę, kiedy przenieśliśmy ten kod do Linuksa (do którego nawet nie dotarliśmy main().
Scheff,
3

To jest fragment kodu dostarczony przez Google w Breakpad.

  volatile int* a = reinterpret_cast<volatile int*>(NULL);
  *a = 1;
Cory Trese
źródło
1
Ponieważ testuję Breakpad, właśnie tego chciałem! Odkryłem, że niektóre minipompy Breakpad nie generują śladu stosu, który wskazuje linię w moim kodzie powodującą awarię. Ten robi, więc mogę go użyć jako dobrego testu poc.
BuvinJ
2
int main(int argc, char *argv[])
{
    char *buf=NULL;buf[0]=0;
    return 0;
}
Aniket Inge
źródło
2

Chociaż to pytanie ma już zaakceptowaną odpowiedź ...

void main(){
    throw 1;
}

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

noɥʇʎԀʎzɐɹƆ
źródło
2

Zapis w pamięci tylko do odczytu spowoduje błąd segmentacji, chyba że system nie obsługuje bloków pamięci tylko do odczytu.

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

Przetestowałem to z MingGW 5.3.0 na Windows 7 i GCC na Linux Mint. Przypuszczam, że inne kompilatory i systemy dadzą podobny efekt.

BEZ NAZWY
źródło
1

Lub w inny sposób, odkąd jesteśmy na wozie zespołu.

Cudowny kawałek nieskończonej rekurencji. Gwarantowane wysadzenie twojego stosu.

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

Wydruki:

Błąd segmentacji (zrzut rdzenia)

Matt
źródło
13
Nazywanie mainsiebie jest tak naprawdę niezdefiniowanym zachowaniem, na wypadek, gdybyś nie wiedział :) Poza tym nie ma gwarancji , że rekurencja ogona zniszczy Twój stos. Jeśli chcesz mieć „gwarancję”, musisz coś zrobić po wywołaniu rekurencyjnym, w przeciwnym razie kompilator może zoptymalizować rekurencję w nieskończoną pętlę.
fredoverflow
0

Ten, o którym jeszcze nie wspomniano:

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

Spowoduje to potraktowanie wskaźnika zerowego jako wskaźnika funkcji, a następnie wywołanie go. Podobnie jak w przypadku większości metod, nie ma gwarancji, że spowoduje to awarię programu, ale szanse systemu operacyjnego na pozostawienie go niezaznaczonego i powrotu programu są znikome.

Anton Golov
źródło
3
Wiem na kilku komputerach, że spowoduje to ponowne uruchomienie, ponieważ kod startowy systemu operacyjnego jest skutecznie odwzorowany na adres 0. Nie zakładaj, że wszystko będzie działało jak twój komputer. Można powiedzieć, że była to awaria, ale nie jest to bardzo przydatne, ponieważ nie można go debugować, ponieważ wszystkie stany są usuwane podczas uruchamiania.
Martin York,
@Loki Astari: Powiem jednak, że jest to awaria - jeśli może to spowodować, program może być również debugowany, co oznacza, że ​​jest tak samo dobry jak test. Z drugiej strony jestem ciekawy, która z tych maszyn może uruchomić Pythona.
Anton Golov,
Myślę, że nie trafiłeś w sedno. Widziałem kod systemu operacyjnego na 0. Nie oznacza to, że nie ma systemów z normalnym dobrym kodem do uruchomienia, które działałyby dobrze na 0. Lub bajty na 0 mogłyby równie dobrze być kodem operacji powrotu.
Martin York,
Znam kod systemu operacyjnego na 0; jest to jeden z powodów, dla których mocno wątpię, że bajty w punkcie 0 byłyby kodem operacji do zwrotu. Program najwyraźniej już nie wykonuje i nie zakończył działania w zwykły sposób, tzn. Zawiesił się - jeśli nie jest to wystarczające dla pytającego, oczekuję, że sam go skomentuje.
Anton Golov,
2
Znasz kod systemu operacyjnego tylko dla twojego komputera. Próbuję powiedzieć, że może się to nie udać. Ale to nic nie znaczy. Istnieje wiele systemów. Jestem pewien, że niektóre z nich mogą działać (tj. Jak bez awarii). Poleganie na specyficznych zachowaniach maszyny / systemu operacyjnego jest złym pomysłem i na dłuższą metę powoduje problemy z konserwacją. Ideą witryny jest promowanie dobrego kodu (nie tylko tego rodzaju kodu).
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;
  }

}

Mam nadzieję, że to się zawiesi. Twoje zdrowie.

sentil
źródło
0
int main()
{
    int *p=3;
    int s;
    while(1) {
        s=*p;
        p++;
    }
}
sc_cs
źródło
2
Byłoby wspaniale wyjaśnić :)
olyv
1
wskaźnik p przejdzie poza przestrzeń adresową programu, co będzie błędem pamięci, ponieważ proces nie może uzyskać dostępu do pamięci innego procesu. Spowoduje to awarię programu. wskaźnik p wskazuje na losową lokalizację w swojej przestrzeni adresowej, jeśli zostanie inkrementowany i dereferencyjnie nieskończenie w pewnym momencie, wskaże przestrzeń adresową (procesową) innego programu. więc po pewnym czasie ulegnie awarii.
sc_cs
Lub hipotetycznie mogłoby to spowodować przepełnienie liczb całkowitych i zawinięcie się, działając nieskończenie. Spróbowałbym użyć long longlub size_ti zacząć pod odpowiedniej maksymalnej wartości lub blisko niej, aby szybciej ulec awarii. Chociaż nadal nie ma gwarancji awarii nawet w tym przypadku.
Patrick Roberts,
0

Stylowym sposobem na zrobienie tego jest czysto wirtualne wywołanie funkcji:

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;
}

Skompilowany z gcc, wyświetla:

czysta wirtualna metoda o nazwie

terminate wywoływany bez aktywnego wyjątku

Przerwane (zrzut rdzenia)

Martin Broadhurst
źródło
0

Możesz użyć asemblera w swoim c ++ code ALE INT 3 jest tylko dla systemów x86, inne systemy mogą mieć inne instrukcje pułapki / punktu przerwania.

int main()
{
    __asm int 3;

    return 0;
}

INT 3 powoduje przerwanie i wywołuje wektor przerwania ustawiony przez system operacyjny.

BattleTested
źródło
0

Użyj __builtin_trap () w GCC lub clang, lub __debugbreak () w MSVC. Brak obsługi tych punktów przerwania / pułapek doprowadzi do nieobsługiwanego wyjątku / awarii punktu przerwania. Inne sugestie, które używają abort () lub exit (): mogą być obsługiwane przez inne wątki, co utrudnia zobaczenie stosu wątku, który propagował awarię.

G Huxley
źródło
-2
char*freeThis;
free(freeThis);

Uwolnienie niezainicjowanego wskaźnika jest niezdefiniowanym zachowaniem. Na wielu platformach / kompilatorach freeThisbędzie miał losową wartość (cokolwiek wcześniej znajdowało się w tym miejscu pamięci). Zwolnienie go spowoduje, że system zwolni pamięć pod tym adresem, co zwykle spowoduje błąd segmentacji i spowoduje awarię programu.

Z Rev
źródło