2010-06-12 5 views
5

내 프로그램은 실행될 때마다 정확하게 똑같이 수행됩니다 (포인트 스프라이트를 멀리 떨어 뜨리면) 터미널 '불법 명령어'의 텍스트가 무작위로 실패합니다. 내 인터넷 검색은 사람들이 이런 종류의 오류를 throw하기 때문에 사람들이 어셈블리를 작성할 때이 사실을 발견했습니다.리눅스에서 C++ 프로그래밍시 불법 명령어

하지만 왜 g ++가 이와 같이 불법적 인 명령어를 생성합니까? Windows 용으로 컴파일하고 Linux에서 실행하는 것과는 다릅니다 (두 경우 모두 x86에서 AFAIK로 잘못된 명령을 내 보내면 안됩니다). 아래에 주 파일을 게시합니다.

안정적으로 오류를 재현 할 수 없습니다. 비록 무작위적인 변경 (여기에 공간을 추가하고 거기서 상수를 변경)을하면 재 컴파일이 강제 실행됩니다. 중단 점을 설정하려고 할 때까지 불법 명령이 실행될 때마다 실패 할 수있는 바이너리를 얻을 수 있습니다. 불법적 인 지시 'dissapear'. :(

#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

결함이있는 메모리 모듈을 교체하는 것이 좋습니다. – avakar

+3

결함있는 주석 작성자를 바꾸는 것이 좋습니다. –

+2

gdb에서 코드를 실행 한 다음 예외가 발생하면 역 추적 (bt)을 수행합니다. –

답변

17

컴파일러는 99.99 %의 확률로, 불법 예외가 생성되지는. 거의 확실히 어떤 일어나고있는 것은 당신이 중 하나) 당신의 실행 코드의 일부를 덮어 일으키는 프로그램의 버그를 가지고있다 쓰레기 데이터가 있거나 b) 쓰레기를 가리키는 함수 포인터를 사용하십시오. 문제를 진단하려면 valgrind에서 프로그램을 실행 해보십시오 (http://valgrind.org/).

+2

(b)의 변형은 C++에서주의해야 할 것은 어떤 식 으로든 덮어 쓴 객체에 가상 함수를 호출하는 것입니다. –

+2

"99.99 % 확률"이라고 말하지 않습니다. 불법적 인 지시를 내리는 컴파일러를 얻는 것은 상당히 쉽습니다. 단지 CPU에 관한 것입니다. 컴파일러에게 AVX2 명령어를 사용하는 것이 좋으며 CPU에 실제로 명령어가 없다면 첫 번째 AVX2 명령어를 실행하면 "잘못된 명령어"로 프로그램이 중단됩니다. – MSalters

0

불법 명령어 버그는 결함이있는 그래픽 카드 드라이버의 증상 일 수도 있고 하드웨어와 일치하지 않는 증상 일 수도 있습니다. 하드웨어가 실제로 무엇인지 확인하려면 lspci | grep VGA을 사용하십시오. 그런 다음 하드웨어 모델에 가장 적합한 최신 드라이버 &을 다운로드하십시오.

멀티 코어 64 비트 시스템의 NetBeans 6.8에서 코드를 실행할 때 알려진 버그가 있습니다. 코드는 프로파일 러의 경쟁 조건을 기반으로 잘못된 명령으로 확률 적으로 충돌합니다. 크래시의 비율은로드되는 라이브러리에 따라 일부 코드에서는 1 % 또는 5 %, 30 % 또는 50 %에서 최대 95 % +까지 다양합니다. 그래픽과 쓰레드 코드는 이것을 증가시키는 것으로 보이지만, 당신은 사소한 Hello World 메인으로 그것을 볼 수 있습니다. 1 % 충돌 률을 얻는다면, 이전에 그 사실을 눈치 채지 못했을 것입니다. 해결책 : 가능한 경우 터미널에서 실행 파일을 바로 실행하십시오.