7 votes

Instruction illégale lors de la programmation de C++ sous Linux

Mon programme, qui fait exactement la même chose à chaque fois qu'il s'exécute (déplacer un sprite ponctuel au loin), échoue de manière aléatoire avec le texte suivant sur le terminal : "Instruction illégale". En cherchant sur Google, j'ai trouvé des gens qui rencontrent ce problème en écrivant de l'assembleur, ce qui est logique puisque l'assembleur génère ce genre d'erreurs.

Mais pourquoi g++ générerait-il une instruction illégale comme celle-ci ? Ce n'est pas comme si je compilais pour Windows et que j'exécutais ensuite sous Linux (ce qui, même dans ce cas, tant que les deux sont sur x86, ne devrait pas AFAIK causer une instruction illégale). Je vais poster le fichier principal ci-dessous.

Je ne peux pas reproduire l'erreur de manière fiable. Cependant, si je fais des changements aléatoires (ajouter un espace ici, changer une constante là) qui forcent une recompilation, je peux obtenir un binaire qui échouera avec une instruction illégale à chaque exécution, jusqu'à ce que j'essaie de mettre un point d'arrêt, ce qui fait "disparaître" l'instruction illégale.

#include <stdio.h>
#include <stdlib.h> 
#include <GL/gl.h>
#include <GL/glu.h>

#include <SDL/SDL.h>

#include "Screen.h"  //Simple SDL wrapper
#include "Textures.h" //Simple OpenGL texture wrapper 
#include "PointSprites.h" //Simple point sprites wrapper

double counter = 0;
/* Here goes our drawing code */
int drawGLScene()
{
    /* These are to calculate our fps */
    static GLint T0     = 0;
    static GLint Frames = 0;

    /* Move Left 1.5 Units And Into The Screen 6.0 */
    glLoadIdentity();
 glTranslatef(0.0f, 0.0f, -6);
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

 glEnable(GL_POINT_SPRITE_ARB);
 glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
    glBegin( GL_POINTS );   /* Drawing Using Triangles */
 glVertex3d(0.0,0.0, 0);
 glVertex3d(1.0,0.0, 0);
 glVertex3d(1.0,1.0, counter);
 glVertex3d(0.0,1.0, 0);
    glEnd( );                           /* Finished Drawing The Triangle */

    /* Move Right 3 Units */

    /* Draw it to the screen */

    SDL_GL_SwapBuffers( );
    /* Gather our frames per second */
    Frames++;
    {
 GLint t = SDL_GetTicks();
 if (t - T0 >= 50) {
     GLfloat seconds = (t - T0) / 1000.0;
     GLfloat fps = Frames / seconds;
     printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
     T0 = t;
     Frames = 0;
  counter -= .1;
 }
    }

    return 1;
}

GLuint objectID;
int main( int argc, char **argv )
{
 Screen screen;
 screen.init();
 screen.resize(800,600);

 LoadBMP("./dist/Debug/GNU-Linux-x86/particle.bmp");
 InitPointSprites();

 while(true){drawGLScene();} 
}

1 votes

Je suggère de remplacer les modules de mémoire défectueux.

6 votes

Je suggère de remplacer l'auteur du commentaire défectueux.

2 votes

Exécutez votre code sous gdb et lorsque vous obtenez l'exception, faites un backtrace (bt).

22voto

JSBձոգչ Points 25069

Le compilateur ne génère pas d'exceptions illégales, avec une probabilité de 99,99 %. Il est presque certain que ce qui se passe, c'est qu'il y a un bogue dans votre programme qui fait que soit a) il écrase des parties de votre code exécutable avec des données inutiles, soit b) il utilise un pointeur de fonction qui pointe vers des données inutiles. Essayez d'exécuter votre programme sous valgrind pour diagnostiquer le problème. http://valgrind.org/ .

3 votes

Une variante de (b) dont il faut se méfier en C++ est l'appel d'une fonction virtuelle sur un objet qui a été écrasé d'une manière ou d'une autre.

5 votes

Je ne dirais pas "probabilité de 99,99 %". Il est assez facile de faire en sorte qu'un compilateur émette des instructions illégales, il suffit de mentir sur votre CPU. Si vous dites au compilateur que vous pouvez utiliser les instructions AVX2, et que votre CPU ne les possède pas, l'exécution de la première instruction AVX2 arrêtera votre programme avec cette "instruction illégale".

1voto

DragonLord Points 1334

Le bogue des instructions illégales peut également être le symptôme d'un pilote de carte graphique défectueux ou mal adapté au matériel. Utilisez lspci | grep VGA pour confirmer ce qu'est réellement votre matériel. Essayez ensuite de télécharger le dernier et meilleur pilote pour votre modèle de matériel.

Il existe également un bogue connu lors de l'exécution de code depuis l'intérieur de NetBeans 6.8 sur une machine 64 bits multi-core. Le code se plante de manière stochastique avec une instruction illégale basée sur des conditions de course dans le profileur. Le pourcentage de plantages varie de 1 % ou 5 % pour certains codes, 30 % ou 50 %, jusqu'à environ 95 %+, en fonction des bibliothèques qui sont chargées. Le code graphique et les threads semblent augmenter ce pourcentage, mais vous pouvez le voir avec une main triviale Hello World. Si vous obtenez un taux de plantage de 1%, vous ne l'avez probablement pas remarqué auparavant. Solution : exécutez l'exécutable directement depuis un terminal, si vous le pouvez.

0voto

Pato Sandaña Points 325

Il est fort probable que vos pilotes soient Mesa Software Rendering ou un pilote de carte graphique défectueux. Mesa utilise parfois un ensemble spécial d'instructions comme AVX, AVX2, entre autres.

Votre glEnable(GL_POINT_SPRITE_ARB); Le code peut activer une pièce de Mesa qui n'est pas destinée à votre CPU.

Je sais que ce message est ancien, mais il pourrait aider d'autres personnes à l'avenir.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X