Quelle est la façon la plus simple de faire planter un programme C ++?

319

J'essaie de créer un programme Python qui s'interface avec un autre processus brutal (c'est hors de ma portée). Malheureusement, le programme avec lequel je m'interface ne plante même pas de manière fiable! Je veux donc créer un programme C ++ rapide qui se bloque exprès, mais je ne connais pas vraiment la meilleure et la plus courte façon de le faire, est-ce que quelqu'un sait quoi mettre entre mes:

int main() {
    crashyCodeGoesHere();
}

faire planter mon programme C ++ de manière fiable

jonathan topf
la source
4
vous pouvez utiliser l'assemblage en ligne pour tenter d'exécuter des instructions privilégiées:asm { cli; };
Nate Koppenhaver
@aitchnyu Je pense qu'il y a une différence dans la facilité d'utilisation des réponses à chaque question. (Pour info: je n'ai voté pour aucune des deux questions)
Andrew Barber
tout commentaire de levée d'exception alors que l'on propage déjà ?? plz chk ma réponse ci-dessous et commentaire
Abhinav
4
Redis utilise le *((char*)-1) = 'x';code suivant pour provoquer un plantage afin de déboguer en savoir plus dans ma réponse ici
Shafik Yaghmour
J'ai trouvé cette question à la recherche d'un cas de test pour un système de rapport de crash. J'avais besoin de forcer un crash pendant l'exécution normale pour invoquer le reporter de crash et l'envoi de vidage de pile. Merci!
Cory Trese

Réponses:

265

La abort()fonction est probablement votre meilleur choix. Il fait partie de la bibliothèque standard C et est défini comme «provoquant une fin anormale du programme» (par exemple, une erreur fatale ou un crash).

duskwuff -inactif-
la source
14
Notez qu'un crash à travers abort()n'appelle aucun destructeur ou atexitfonction, bien que cela n'ait probablement pas d'importance ici.
Xeo
139
@Xeo: S'il appelait des destructeurs et des atexits, ce ne serait pas un crash maintenant?
Donal Fellows du
Puisque abort()c'est la bonne réponse, alors 'exit (-1); `devrait être acceptable?
asir6
9
Non, car cela ne provoque pas de plantage, signale simplement que quelque chose ne peut pas être fait.
Boatcoder
Les fenêtres. GCC-5.4.0. Code de sortie: 3. Aucune boîte de message d'erreur. Message de la console: "Cette application a demandé au runtime de le terminer de manière inhabituelle. Veuillez contacter l'équipe d'assistance de l'application pour plus d'informations.".
Vadzim
113

Essayer:

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

Trouvé dans:

#include <signal.h>
Martin York
la source
3
C'est plus que simplement défini par l'implémentation - le signal peut être capturé signal(). Cependant, la plupart des applications sensées ne le font pas.
duskwuff -inactive-
12
Il se bloquera exactement de la même manière qu'un SIGSEGV normal dans l'application (qui est la façon dont la plupart des applications se bloquent). Il est bien défini ce qu'il fait (par défaut, il quitte l'application et génère un fichier core). Oui, vous pouvez définir un gestionnaire, mais si vous en avez un, vous ne voulez pas le tester de la même manière !!
Martin York
1
+1 pour raise(). Cela vous permet de tester une tonne de différents types d'exceptions en changeant simplement l'argument.
3
solution préférée, mais elle dépend de la plate-forme.
Nadim Farhat
@NadimFarhat: De quelle manière. Un signal est un signal sur toutes les plateformes.
Martin York
74

Si vous divisez par zéro, l'application se bloquera:

int main()
{
    return 1 / 0;
}
Roee Gavirel
la source
29
Selon la façon dont votre compilateur est intelligent, cela sera capturé au moment de la compilation. Je sais que Visual Studio 2008 ne compilera pas cela pour c ++ ou c #.
AidanO
2
Je l'ai compilé et exécuté, voulez-vous que je vous ponce le .exe?
Roee Gavirel
1
Dans la configuration des versions dans les versions récentes de Visual Studio comme 2010, il s'exécutera sans problème. Je suppose que c'est une optimisation.
tedyyu
2
iirc il ne plante pas sur le bras
sherpya
2
Il s'agit d'un comportement non défini et il n'est pas garanti de se bloquer. Souvent, les compilateurs supposent qu'un comportement non défini est inaccessible. Cela peut entraîner la mainsuppression complète du corps, y compris l' retinstruction. L'exécution pourrait simplement tomber dans la fonction suivante.
usr
64
*((unsigned int*)0) = 0xDEAD;
Keith Nicholas
la source
54
Ce n'est pas garanti de planter.
Programmeur Windows
8
@Windowsprogrammer: non, ce n'est pas garanti . Mais quel système d'exploitation sain n'arrête pas une application qui essaie d'accéder à la mémoire à l'adresse 0?
Joachim Sauer
29
"Mais quel système d'exploitation sain n'arrête pas une application qui essaie d'accéder à la mémoire à l'adresse 0?" - Ce n'est pas vraiment ce que tu veux demander, mais je répondrai quand même. Dans certains ordinateurs, il y a de la RAM à l'adresse 0, et il est parfaitement significatif qu'un programme y stocke une valeur. Une question plus significative serait "Quel système d'exploitation n'arrête pas une application qui accède à la mémoire à l'adresse qu'une implémentation C ++ a réservée à un pointeur nul?" Dans ce cas, je n'en connais aucun. Mais le programme d'origine concerne le langage C ++ et non les OS.
Programmeur Windows
6
Son comportement indéfini. Il est parfaitement normal que cela ne fasse rien. Une machine qui ne tombera pas en panne: tout ce qui exécute un processeur de la série Z80 (je suppose (mon Z80a ne fait rien)).
Martin York
28
Bien que cela ne soit pas garanti de se bloquer, il s'agit de l'un des types de plantage les plus courants en C ++. Donc, si vous voulez simuler un crash, c'est une façon "authentique" de le faire :)
Chris Burt-Brown
53

Eh bien, sommes-nous en débordement de pile , ou non?

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

(Il n'est pas garanti de planter selon les normes, mais aucune des réponses suggérées, y compris celle acceptée, car elle SIGABRTaurait pu être interceptée de toute façon. En pratique, cela plantera partout.)

sam hocevar
la source
4
Je peux voir que c'est drôle sur un système avec des pages de codes non protégées et que vous écrasez votre programme avec du code qui est accidentellement une boucle infinie qui ne fait rien. Très hautement hautement hautement improbable mais potentiellement possible.
Martin York
@Loki: Que se passe-t-il s'il lit simplement tous les 4000 octets? Serait-ce moins susceptible de planter? Certainement moins dangereux.
Mooing Duck
70
Cet algorithme de plantage n'est pas O (1)!
Anton Barkovsky
@MooingDuck: Je fais juste un drôle de commentaire. Ne prenez pas cela au sérieux :-) Mais il serait intéressant que quelqu'un trouve une séquence d'instructions qui fasse quelque chose de drôle.
Martin York
1
@LokiAstari: vous avez absolument raison. Je pensais à la (&i)[i] += !iplace, mais je craignais que le compilateur soit assez intelligent et que je veuille l'optimiser. :-)
sam hocevar
35
 throw 42;

Juste la réponse ... :)

Macke
la source
1
Les fenêtres. GCC-5.4.0. Code de sortie: 3. Aucune boîte de message d'erreur. Message de la console: "Terminer appelé après avoir lancé une instance de 'int' Cette application a demandé au Runtime de la terminer de manière inhabituelle. Veuillez contacter l'équipe de support de l'application pour plus d'informations.".
Vadzim
15

assert(false); est assez bon aussi.

Selon ISO / IEC 9899: 1999, il est garanti de se bloquer lorsque NDEBUG n'est pas défini:

Si NDEBUG est défini, la macro [...] assert est définie simplement comme

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

La macro d'assertion est redéfinie en fonction de l'état actuel de NDEBUG chaque fois qu'il est inclus.

[...]

La macro assert place les tests de diagnostic dans les programmes; [...] si l'expression (qui doit avoir un type scalaire) est fausse [...]. Il appelle ensuite la fonction d'abandon.

Dan F
la source
Je me souviens vaguement que VC 2005 se comportait différemment entre le débogage et la libération avec assertions?
Tom Kerr
8
@Tom assertest rendu équivalent au ((void)0)mode Release.
Seth Carnegie
2
@SethCarnegie Ne voyez pas ce qui ne va pas avec cela - seulement si la volonté définie par NDEBUG ne se bloque pas? Dans réponse était assez juste à mon humble avis.
Adrian Cornish
@AdrianCornish Je répondais seulement à la question de Tom Kerr, sans dire que cette réponse était fausse. Je n'ai pas déçu cette réponse.
Seth Carnegie
3
Je ne sais pas pourquoi il ferait une version "release" de ce code de test.
Joel B
11

Puisqu'un crash est un symptôme d'invocation d'un comportement non défini, et puisque l'invocation d'un comportement non défini peut conduire à n'importe quoi, y compris un crash, je ne pense pas que vous vouliez vraiment planter votre programme, mais faites-le simplement tomber dans un débogueur. La façon la plus portable de le faire est probablementabort() .

Bien que cela raise(SIGABRT)ait le même effet, c'est certainement plus à écrire. Les deux manières peuvent cependant être interceptées en installant un gestionnaire de signaux pour SIGABRT. Donc, selon votre situation, vous voudrez peut-être / devrez lever un autre signal. SIGFPE, SIGILL, SIGINT, SIGTERMOuSIGSEGV peut - être la voie à suivre, mais ils peuvent tous être interceptés.

Lorsque vous ne pouvez pas être transférable, vos choix peuvent être encore plus larges, comme l'utilisation SIGBUSsur Linux.

PlasmaHH
la source
1
Je doute vraiment qu'il veuille un débogueur impliqué. Il semble vouloir tester ce qui se passe lorsque l'appelant d'un programme en panne se fait envoyer un crash. Ce qui est très raisonnable.
Donal Fellows
9

Le seul flash que j'ai eu est la fonction abort () :

Il interrompt le processus avec une fin de programme anormale.Il génère le signal SIGABRT , qui par défaut provoque la fin du programme renvoyant un code d'erreur de fin infructueuse à l'environnement hôte.Le programme est terminé sans exécuter de destructeurs pour les objets de durée de stockage automatique ou statique et sans faire appel à tout atexit (qui est appelé par la sortie () avant que se termine le programme) fonction. Il ne revient jamais à son appelant.

samridhi
la source
9

La réponse est spécifique à la plateforme et dépend de vos objectifs. Mais voici la fonction de crash de Mozilla Javascript, qui, je pense, illustre beaucoup de défis pour faire fonctionner cela:

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
la source
2
Vous devez totalement supprimer cela et utiliser jQuery à la place.
Thomas Weller
1
Il s'agit d'un comportement non défini et il n'est pas garanti de se bloquer. Souvent, les compilateurs supposent qu'un comportement non défini est inaccessible. Dans ce cas, au moins la ligne qui plante va être supprimée et d'autres codes pourraient l'être également.
usr
8

Je vois qu'il y a beaucoup de réponses publiées ici qui tomberont dans des cas chanceux pour faire le travail, mais aucune d'entre elles n'est 100% déterministe pour planter. Certains tomberont en panne sur un matériel et un système d'exploitation, d'autres non. Cependant, il existe un moyen standard selon la norme C ++ officielle de le faire planter.

Citant de la norme C ++ ISO / IEC 14882 §15.1-7 :

Si le mécanisme de gestion des exceptions, après avoir terminé l'initialisation de l'objet exception mais avant l'activation d'un gestionnaire pour l'exception, appelle une fonction qui se termine via une exception, std :: terminate est appelé (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) { }
}

J'ai écrit un petit code pour le démontrer et je peux le trouver et l'essayer sur Ideone ici .

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

L'ISO / CEI 14882 §15.1 / 9 mentionne un lancer sans bloc d'essai entraînant un appel implicite à l'abandon:

Si aucune exception n'est actuellement gérée, l'exécution d'une expression de lancement sans opérande appelle std :: terminate ()

Autres: jet du destructeur: ISO / IEC 14882 §15.2 / 3

Abhinav
la source
7
*( ( char* ) NULL ) = 0;

Cela produira un défaut de segmentation.

wrren
la source
10
Ce n'est pas garanti de planter.
Programmeur Windows
23
"Que va-t-il arriver à la place?" - Tout pourrait arriver à la place. Le comportement n'est pas défini, donc l'implémentation pourrait affecter 0 à l'une des variables de votre programme, ou elle pourrait affecter 42 à l'une des variables de votre programme, ou elle pourrait formater votre disque dur et continuer à exécuter votre programme.
Programmeur Windows
7
(état d'esprit continu du "programmeur Windows") Cela peut faire exploser votre ordinateur, ou le faire vivre et prendre le dessus sur l'humanité. ou ... il va planter à 99,9% et il est défini comme un "comportement indéfini" car personne ne veut en assumer la responsabilité.
Roee Gavirel
1
En fait, cela ne garantit même pas un comportement indéfini - il pourrait être complètement défini et fonctionner correctement. Considérez ce code: pastebin.com/WXCtTiDD (testé sous Linux en tant que root, vous pouvez également le faire en tant qu'utilisateur non root si vous effectuez des modifications de configuration wiki.debian.org/mmap_min_addr )
cha0site
2
@ cha0site: Il est garanti que le comportement n'est pas défini par la norme, car cela déréférence un pointeur nul. Quel que soit le comportement que vous avez observé sous Linux, il est autorisé sous l'égide du "comportement indéfini"
Ben Voigt
6

Celui-ci manque:

int main = 42;
mvds
la source
1
Oui; mais il fait quelque chose de spectaculaire lorsque vous l'exécutez.
Joshua
5

Qu'en est-il du débordement de pile par un appel de méthode récursive en boucle morte?

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

Voir l' exemple d'origine sur Microsoft KB

sll
la source
4
Qu'est-ce qui empêcherait un compilateur suffisamment intelligent d'optimiser à la fois l'allocation de pile inutilisée et l'appel final?
JB.
@JB: malheureusement, nous n'en avons aucune idée car nous ne connaissons pas la logique d'optimisation des compilateurs existants
sll
8
Eh bien, compilé ici avec gcc 4.6.0 aux niveaux d'optimisation -O2 et au-dessus, il optimise très bien. Il a besoin de -O1 ou inférieur pour segfault.
JB.
@Abhinav: Il suffit de poster votre réponse avec toutes ces façons exprimées en exemples en C ++ :)
sll
5

Cela se bloque sur mon système Linux, car les littéraux de chaîne sont stockés en mémoire morte:

0[""]--;

Soit dit en passant, g ++ refuse de compiler cela. Les compilateurs deviennent de plus en plus intelligents :)

fredoverflow
la source
4
int i = 1 / 0;

Votre compilateur vous avertit probablement à ce sujet, mais il compile très bien sous GCC 4.4.3 Ce sera probablement provoquera un SIGFPE (exception à virgule flottante), ce qui n'est peut-être pas aussi probable dans une application réelle que SIGSEGV (violation de segmentation de mémoire) que les autres réponses causent, mais c'est quand même un crash. À mon avis, c'est beaucoup plus lisible.

Une autre façon, si nous allons tricher et utiliser signal.h, est:

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

Ceci est garanti pour tuer le sous-processus, contrairement à SIGSEGV.


la source
2
Ce n'est pas garanti de planter.
Programmeur Windows
11
Le langage C ++ ne garantit pas que 1/0 provoquera un SIGFPE. Le comportement n'est pas défini. L'implémentation pourrait dire que le résultat est 42.
Programmeur Windows
1
Lorsque le comportement n'est pas défini, l'implémentation peut faire ce qu'elle veut. Le langage C ++ n'empêche ni ne nécessite une implémentation pour écrire un vidage sur incident, le langage C ++ n'empêche ni n'exige une implémentation pour en affecter 42, etc.
Programmeur Windows
2
@Giorgio si le matériel n'a pas de moyen de le piéger automatiquement, vous forcez toujours les compilateurs à émettre au moins deux instructions, dont l'une serait également une branche. Cela représente environ le double du coût d'une division. Tout le monde paie ce coût comme ça. Si c'est facultatif et que vous le souhaitez, vous pouvez toujours utiliser une fonction de bibliothèque pour cela. Si ce n'est pas facultatif et que vous ne le souhaitez pas, vous finirez toujours par en payer le coût.
Flexo
2
@Giorgio: J'ai une application qui fait 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 Je sais pertinemment que 0 d'entre eux sera une division par zéro bien qu'il n'y ait aucun moyen que le compilateur puisse le savoir. Je ne veux certainement pas que le compilateur plante le chèque pour une division par zéro.
Martin York
4

Il s'agit d'une version plus garantie de l'abandon présentée dans les réponses ci-dessus.Elle prend soin de la situation lorsque sigabrt est bloqué.Vous pouvez en fait utiliser n'importe quel signal au lieu d'abandonner qui a pour effet par défaut de planter le programme.

#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
la source
3
int* p=0;
*p=0;

Cela devrait également planter. Sous Windows, il se bloque avec AccessViolation et il devrait faire de même sur tous les systèmes d'exploitation, je suppose.

laci37
la source
5
on all OS-esNon, il ne tombe pas en panne dans le système d' exploitation non protégé (par exemple MS-DOS.) En fait, parfois il est quelque chose dans l' adresse 0! Pour le mode réel x86, Interrupt Vector Table est à l'adresse 0.
ikh
Il ne s'est pas écrasé sur Irix. J'ai malheureusement réalisé quand nous avons porté ce code sur Linux (où nous n'avons même pas atteint main().
Scheff
3

Il s'agit de l'extrait fourni par Google dans Breakpad.

  volatile int* a = reinterpret_cast<volatile int*>(NULL);
  *a = 1;
Cory Trese
la source
1
Depuis que je teste Breakpad, c'est exactement ce que je voulais! J'ai constaté que certains mini-vidages de Breakpad ne produisent pas de trace de pile qui pointe vers la ligne de mon code provoquant le crash. Celui-ci le fait, donc je peux l'utiliser comme bon test de poc.
BuvinJ
2
int main(int argc, char *argv[])
{
    char *buf=NULL;buf[0]=0;
    return 0;
}
Aniket Inge
la source
2

Bien que cette question ait déjà une réponse acceptée ...

void main(){
    throw 1;
}

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

noɥʇʎԀʎzɐɹƆ
la source
2

L'écriture dans une mémoire en lecture seule entraînera une erreur de segmentation, sauf si votre système ne prend pas en charge les blocs de mémoire en lecture seule.

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

Je l'ai testé avec MingGW 5.3.0 sur Windows 7 et GCC sur Linux Mint. Je suppose que d'autres compilateurs et systèmes donneront un effet similaire.

SANS NOM
la source
1

Ou d'une autre manière puisque nous sommes dans le wagon du groupe.

Un joli morceau de récursion infinie. Garanti pour faire exploser votre pile.

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

Imprime:

Segmentation fault (core dumped)

Mat
la source
13
S'appeler mainsoi-même est en fait un comportement indéfini, au cas où vous ne le sauriez pas :) En outre, la récursivité de la queue n'est pas garantie de faire exploser votre pile. Si vous voulez une "garantie", vous devez faire quelque chose après l'appel récursif, sinon le compilateur pourrait optimiser la récursivité dans une boucle infinie.
fredoverflow
0

Celui qui n'a pas encore été mentionné:

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

Cela traitera le pointeur nul comme un pointeur de fonction, puis l'appellera. Tout comme la plupart des méthodes, cela ne garantit pas le plantage du programme, mais les chances que le système d'exploitation laisse cela sans contrôle et que le programme revienne jamais sont négligeables.

Anton Golov
la source
3
Je connais plusieurs machines qui provoqueront un redémarrage car le code de démarrage du système d'exploitation est effectivement mappé à l'adresse 0. Ne présumez pas que tout fonctionnera comme votre PC. Vous pourriez dire que c'était un crash mais ce n'est pas très utile car vous ne pouvez pas le déboguer car tout l'état est effacé au démarrage.
Martin York
@Loki Astari: Je dirai néanmoins qu'il s'agit d'un plantage - si cela peut en être la cause, le programme en cours de débogage peut également le faire, ce qui signifie que c'est aussi un bon test que n'importe quel autre. D'un autre côté, je suis curieux de savoir laquelle de ces machines peut exécuter Python.
Anton Golov
Je pense que vous n'avez pas saisi mon argument. J'ai vu le code du système d'exploitation à 0. Cela ne signifie pas qu'il n'y a pas de système avec un bon code normal à exécuter qui fonctionnera très bien à 0. Ou les octets à 0 pourraient tout aussi bien être l'opcode pour le retour.
Martin York
Je connais le code OS à 0; c'est l'une des raisons pour lesquelles je doute fortement que les octets à 0 soient l'opcode de retour. Le programme ne s'exécute plus clairement et n'est pas sorti de la manière habituelle, c'est-à-dire qu'il s'est écrasé - si cela ne suffit pas pour le demandeur, je m'attends à ce qu'il le commente lui-même.
Anton Golov
2
Vous connaissez uniquement le code du système d'exploitation de votre machine. Ce que j'essaie de dire, c'est que cela peut échouer pour vous. Mais cela ne veut rien dire. Il existe de nombreux systèmes. Je suis sûr que certains d'entre eux peuvent fonctionner (c'est-à-dire comme ne pas planter). Se fier à un comportement spécifique à la machine / au système d'exploitation est une mauvaise idée et provoque des problèmes de maintenance à long terme. L'idée du site est de promouvoir un bon code (pas seulement de coder ce genre de travaux).
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;
  }

}

J'espère que ça plante. À votre santé.

senthil
la source
0
int main()
{
    int *p=3;
    int s;
    while(1) {
        s=*p;
        p++;
    }
}
sc_cs
la source
2
Ce serait génial d'avoir des éclaircissements :)
olyv
1
le pointeur p ira au-delà de l'espace d'adressage du programme qui sera une erreur de mémoire, car un processus ne peut pas accéder à la mémoire d'un autre processus. Cela entraînera le programme de planter. le pointeur p pointe vers un emplacement aléatoire dans son espace d'adressage, s'il est incrémenté et déréférencé infiniment à un moment donné, il pointera vers l'espace d'adressage d'un autre programme (processus). il se bloquera donc après un certain temps.
sc_cs
Ou, hypothétiquement, il pourrait atteindre un débordement d'entier et un bouclage, fonctionnant à l'infini. J'essaierais d'utiliser long longou size_tet commencerais pà la valeur maximale respective, ou à proximité, pour planter plus rapidement. Bien qu'il ne soit toujours pas garanti de planter même dans ce cas.
Patrick Roberts
0

Une façon élégante de le faire est un appel de fonction virtuelle pure:

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

Compilé avec gcc, ceci imprime:

méthode virtuelle pure appelée

terminer appeler sans exception active

Abandonné (core dumpé)

Martin Broadhurst
la source
0

Vous pouvez utiliser l'assemblage dans votre c ++ code MAIS INT 3 c'est uniquement pour les systèmes x86 que d'autres systèmes peuvent avoir d'autres instructions d'interruption / point d'arrêt.

int main()
{
    __asm int 3;

    return 0;
}

INT 3 provoque une interruption et appelle un vecteur d'interruption configuré par le système d'exploitation.

BattleTested
la source
0

Utilisez __builtin_trap () dans GCC ou clang, ou __debugbreak () dans MSVC. Le non-traitement de ces points d'arrêt / interruptions entraînera une exception / panne de point d'arrêt non gérée. Autres suggestions qui utilisent abort () ou exit (): celles-ci peuvent être gérées par d'autres threads, ce qui rend plus difficile la visualisation de la pile du thread qui a propagé le crash.

G Huxley
la source
-2
char*freeThis;
free(freeThis);

La libération d'un pointeur non initialisé est un comportement non défini. Sur de nombreuses plates-formes / compilateurs, freeThisaura une valeur aléatoire (ce qui se trouvait auparavant à cet emplacement mémoire). Le libérer demandera au système de libérer la mémoire à cette adresse, ce qui provoquera généralement une erreur de segmentation et fera planter le programme.

Z Rev
la source