2016-12-07 11 views
1

전역 포인터 변수를 정의하려고합니다.이 포인터 변수는 아래와 같이 main 함수에서 실제로 설정할 수 있습니다. 그러나이 후에 outputName을 사용하려고 할 때마다 세그먼트 오류가 발생합니다. 나는 아마도 처음에 NULL과 같은 포인터를 설정하는 것과 관련이 있다는 것을 알고 있습니다 ... 어떻게하면 메인에 설정되어있는 전역 포인터를 가질 수 있었는지에 대한 도움이 매우 도움이 될 것입니다! 다음은 나에게 오류를주고 내 코드의 일부입니다글로벌 포인터를 사용한 세그먼트 오류

char* outputName=NULL; 

int isNumber(char number[]){ 
int i; 
if (number[0]=='-'){ 
    i=1; 
} 
while(number[i] != '\0'){ 
    if (!isdigit(number[i])){ 
    return 0; 
    } 
    i++; 
} 
return 1; 
} 

void catcher(int signo) { 
printf("The program is exiting early"); 
remove(outputName); 
exit(1); 
} 

int main(int argc, char *argv[]) { 
if (argc != 4){ 
    fprintf(stderr,"Incorrect number of arguments, must supply three.\n"); 
    exit(1); 
} 
char* inputName = argv[1]; 
outputName=argv[2]; 
signal(SIGINT, catcher); 
int result=isNumber(argv[3]); 
if (result==0){ 
    fprintf(stderr, "Invalid maximum line length, please enter an integer\n"); 
    exit(1); 
} 
int maxChars= (atoi(argv[3]))+1; 
if ((maxChars-1)<1){ 
    fprintf(stderr, "Invalid third maximum line length, please enter an integer greater than zero\           
.\n"); 
    exit(1); 
} 
FILE* inFile = fopen(inputName, "r"); 
if (inFile==NULL){ 
    fprintf(stderr,"Error while opening %s.\n", inputName); 
    exit(1); 
} 
FILE* outFile= fopen(outputName, "w"); 
if (outFile==NULL){ 
    fprintf(stderr,"Error while opening %s.\n", outputName); 
    exit(1); 
}                        
char line[maxChars]; 
int done=0; 
while (!done){ 
    char *readLine=fgets(line,maxChars,inFile); 
    if (readLine==NULL){ 
    if (errno==0){ 
     done=1; 
    } 
    else{ 
    fprintf(stderr, "Error when reading line from input file"); 
    exit(1); 
    } 
} 
int len=strlen(line); 
if (line[len-1]!='\n'){ 
    line[len]='\n'; 
    line[len+1]='\0'; 
    char current=' '; 
    while (current != '\n'){ 
    current=getc(inFile); 
    } 
} 
if (!done){ 
    fputs(line, outFile); 
    if (errno!=0){ 
    fprintf(stderr, "Error when writing line to output file"); 
    exit(1); 
    } 
    } 
} 
return 0; 
} 
+0

'main()'에 몇 개의 인수를 전달합니까? 당신은'argv [2]'의 값이 무엇인지보기 위해 기본적인 디버깅을 했습니까? 'argc> = 3'을 확인 했습니까? – John3136

+0

이 네 개의 인수를 전달하면 yes가 모든 오류 검사를 완료하여 are의 값이 올바른지 확인하십시오. – liverr1818

+1

위의 코드 다음에'outputName'이 유효하다면 문제는 다른 곳에서 발생합니다 ... – John3136

답변

3

는, 신호 처리기 outputName 이전에이 null 이외의 값으로 설정하기라는지고있을 수는 outputName = ARGV 후 신호 처리기를 설정하는 시도 할 수있다 [2] ; 주()

2

읽기 주의 깊게signal(7)을에 : 비동기 신호 안전 기능이없는 당신의 catcher 전화 printf 이후 코드는 undefined behavior 있습니다. 또한 printf 제어 문자열은 \n으로 끝나지 않으며 표준 출력은 출력 버퍼가 없기 때문에 출력이 수행되지 않습니다. sigaction(2) ~ signal을 선호하고 outputName이 할당 된 다음에 신호 처리기 을 설치하십시오.

신호 처리기에서 사용되는 전역 변수는 volatile으로 선언해야합니다. 따라서 char* volatile outputName;을 전역 범위로 선언하십시오. 그런 다음 핸들러에 if (outputName != NULL) remove(outputName);과 같은 테스트가있을 수 있습니다. 일반적으로 시그널 핸들러에 volatile sig_atomic_t 글로벌 플래그를 설정하고 그 플래그를 다른 곳에서 테스트하는 것입니다.

그리고 프로그램이 신호를받을 시간이 없을 것 같습니다. main 함수를 잠시 기다려야합니다 (예 : 표준 또는 usleep(3) 또는 pause(2) 또는 poll(2) ....). 물론

는, 디버거 (gdb)를 사용하는 모든 경고 및 디버그 정보 (gcc -Wall -g)와 사용하여 코드를 컴파일; 나는 디버거 watchpoints가 당신의 버그를 발견하는데 매우 유용하다고 생각한다.

보여주는 프로그램에 SEGV가 나타나지 않을 가능성이 있습니다. 따라서 실제 버그는 다른 곳에서 발생할 가능성이 큽니다.

아마도 strace(1) 및/또는 valgrind을 사용하는 것이 도움이 될 수 있습니다.