2016-10-25 2 views
2

파일을 어휘로 분할하는 프로그램을 만들고 있지만 C에 익숙하지 않아 이상한 세분화 오류가 발생합니다. 다음 코드가 실행되고 인쇄는 :간단한 할당으로 인해 세그멘테이션 오류가 발생할 수 있습니까?

1 
2 
Segmentation Fault: 11 

나는 오류를 세그멘테이션 다른 원인을 검토 한 결과 나는 내가 뭘 잘못 2. 후 배열에 아무것도 아니에요? 간단한 할당으로 세분화 오류가 발생할 수 있습니까?

#include <stdio.h> 

#define CHAR_CODE 1 
#define NUM_CODE 2 
#define RESERVED_CHAR_CODE 3 
#define SPACE_CODE 4 
#define ERR_CODE 5 

char token[16]; 
char line[128]; 
int lineLen = 0; 
int counter = 0; 
FILE *file; 

void cleanToken(){ 
    for(int i = 0 ; i < 16; i++){ 
     token[i] = 0; 
    } 
} 

void cleanLine(){ 
    for(int i = 0 ; i < 128; i++){ 
     line[i] = 0; 
    } 
} 

void next(){ 
    cleanToken(); 
    printf("1\n"); 
    char c; 
    if(counter == lineLen){ 
     printf("2\n"); 
     lineLen = 0; 
     printf("3"); 
     cleanLine(); 
     printf("4"); 
     counter = 0; 
     while((c=getc(file)) != 10 && c != EOF){ 
      if(c!=32){ 
       line[lineLen] = c; 
       lineLen++; 
      } 
      printf("%d\n", lineLen); 
     } 
     printf("%s\n", line); 
    } 
    c = line[counter]; 
    int type = getType(c); 
    while(getType(c)==type){ 
     token[counter] = c; 
     counter = counter + 1; 
     c = line[counter]; 
     if(c == EOF | c == 4 | type == RESERVED_CHAR_CODE){ 
      break; 
     } 
    } 
} 

int getType(int c){ 
    if((c > 96 & c < 123) | (c>64 & c < 91)){ 
     return CHAR_CODE; 
    } else if(c < 58 & c > 46){ 
     return NUM_CODE; 
    } else if(c == 32){ 
     return SPACE_CODE; 
    } else if(c == 33 | c == 34 | (c > 36 & c < 44) | c == 45 | c == 47 | (c > 58 & c < 63)){ 

     return RESERVED_CHAR_CODE; 
    } else { 
     return ERR_CODE; 
    } 
} 

int main(){ 
    int c; 
    FILE* file; 
    file = fopen("test.txt", "r"); 
    for(int i = 0; i < 10 ;i++){ 
     next(); 
     printf("%s\n", token); 
    } 
    return 0; 
} 
+1

모든 경고가 활성화 된 상태에서 컴파일하십시오. –

+1

'test.txt' 파일에는 무엇이 있습니까? –

+0

코드를 들여 줘서 최소한의 예제를 제공하십시오 ... 그런 간단한 'printf' 문에 대한 seg 오류는 대개 토큰이 제대로 null 종료되지 않는다는 것을 의미합니다. –

답변

7

이되지 않은 전역 변수 file에 액세스 시도하여 컴파일 할 때 -Wall를 사용하여 표시되지만 특히, 충돌이 발생되고있는 대부분의 코드에서 문제가 있습니다 초기화되었습니다.

동일한 이름의 다른 변수를 사용하여 main()에 음영 처리했습니다. 이 중 하나를 초기화했지만 은 글로벌 주소가 아닌 next()입니다.

또한 printf 문은 프로그램이 충돌하기 전에 출력 버퍼가 콘솔로 플러시되지 않는다고 보장 할 수 없으므로 디버깅에는 충분하지 않습니다. 을 printf("3") and printf("4") 행에 추가하면 충돌 이전에 인쇄 된 것을 볼 수 있습니다. 또는 printf() 호출 후에 fflush(stdout)으로 호출하여 인쇄되었는지 확인할 수 있습니다. 이렇게하면 충돌이 나타나는 과제의 결과로 발생하지 않음을 알 수 있습니다.

gdb과 같은 디버거는 코드 디버깅에 매우 유용합니다.

3

편집

DERP. eddiem의 대답을 보았습니다. 그가 맞습니다. 이것이 코드의 실제 문제입니다.

그러나 루프에 lineLen 수표를 추가해야합니다.

ORIGINAL

곧 문제가 여기에 진짜 돈을 내기 :

파일이 한 줄에 128 개 이상의 문자를 포함하면 어떻게됩니까
while((c=getc(file)) != 10 && c != EOF){ 
    if(c!=32){ 
     line[lineLen] = c; 
     lineLen++; 
    } 

? 당신은 모든 종류의 신체 상해를 초래할 수있는 당신의 배열 끝을지나면서 글을 쓰고 있습니다. 당신이 그 printf에서 줄 바꿈이 없기 때문에 당신은 34 출력을 표시되지 않는

while (lineLen < 128 && (c = getc(file)) != 10 && c != EOF) { ... } 

:

당신은 당신이 당신의 배열 범위를 초과하지 않는 확인하기 위해 검사를 추가해야 진술. stdout은 일반적으로 라인 버퍼이며, 이는 버퍼가 가득 차거나 개행 문자가 보내지지 않으면 출력이 터미널에 나타나지 않음을 의미합니다.

2

두 개의 서로 다른 file 변수가 있습니다. 하나는 프로그램 상단에 선언 된 전역 변수이고 다른 하나는 main 함수의 전역 변수입니다.

그리고 next 함수에서는 할당되지 않은 전역 file 함수를 사용합니다.

#include <stdio.h> 
... 
FILE *file; // <<< global one 
... 


int main() { 
    int c; 
    FILE* file; // <<<local one 

    file = fopen("x.txt", "r"); 
    ... 
    return 0; 
} 

왜 글로벌 변수를 남용하면 문제가 발생하는지 보여주는 또 다른 예입니다.

다른 문제가있을 수 있습니다.

관련 문제