2016-06-04 2 views
-1

파일을 읽어야하고 getline 함수를 사용해야합니다. 다음은이 웹 사이트의 한 예입니다 : 파일을 열 수있게하기 위해 내가 조정 한 http://crasseux.com/books/ctutorial/getline.html.C에서 세그먼트 오류가 발생합니다.

#include <stdio.h> 
#include <stdlib.h> 


int main() 
    { 
    int bytes_read; 
    unsigned long nbytes = 100; 
    char *my_string; 
    char *filename; 
    char *line; 
    FILE *fd = NULL; 


    puts ("enter filename"); 

    filename = (char *) malloc (nbytes + 1); 

    bytes_read = getline (&filename, &nbytes, stdin); 

    fd = fopen(filename, "r"); 

    bytes_read = getline (&line, &nbytes, fd); 

    puts (line); 

    puts ("Please enter a line of text."); 

    /* These 2 lines are the heart of the program. */ 
    my_string = (char *) malloc (nbytes + 1); 
    bytes_read = getline (&my_string, &nbytes, stdin); 

    if (bytes_read == -1) 
    { 
     puts ("ERROR!"); 
    } 
    else 
    { 
     puts ("You typed:"); 
     puts (my_string); 
    } 

    return 0; 
} 

그리고 프로그램을 실행할 때 Segmentation 오류 11이 발생하고 내가 무엇을 잘못하고 있는지 알지 못합니다. 미리 감사드립니다.

+2

파일을 성공적으로 열 었는지 항상 확인하십시오. get 줄에서 반환 된 문자열에서 줄 바꿈을 제거하지 않았으므로 이름 끝에 줄 바꿈이있는 파일을 열지 않았을 것입니다. –

+2

또한, 파일 디스크립터 (int 형)에'fd'를 사용하고 파일 포인터 ('FILE *'형)에 대해'fp'를 사용하는 것이 일반적입니다. –

답변

1

filename stdin에서 읽는 것이 파일 파일 인수에 잘못되었습니다. 예를 들어, 입력 a.txt 일 때 filename stdin에서 str 값이 'a.txt \ n'입니다.

그래서 '\ n'을 '\ 0'으로 수정하면 문제가 해결됩니다. 즉 bytes_read = getline (&filename, &nbytes, stdin); 문 바로 아래에 filename[bytes_read - 1] = '\0'; 문장이 추가됩니다.

#include <stdio.h> 
#include <stdlib.h> 


int main() 
    { 
    int bytes_read; 
    unsigned long nbytes = 100; 
    char *my_string; 
    char *filename; 
    char *line; 
    FILE *fd = NULL; 


    puts ("enter filename"); 

    filename = (char *) malloc (nbytes + 1); 

    bytes_read = getline (&filename, &nbytes, stdin); 

    filename[bytes_read - 1] = '\0'; 

    fd = fopen(filename, "r"); 

    bytes_read = getline (&line, &nbytes, fd); 

    puts (line); 

    puts ("Please enter a line of text."); 

    /* These 2 lines are the heart of the program. */ 
    my_string = (char *) malloc (nbytes + 1); 
    bytes_read = getline (&my_string, &nbytes, stdin); 

    if (bytes_read == -1) 
    { 
     puts ("ERROR!"); 
    } 
    else 
    { 
     puts ("You typed:"); 
     puts (my_string); 
    } 

    return 0; 
} 
+1

그래서 "버그"는 실제로 오류 검사를 생략 한 것입니다. – alk

+1

이름을 입력 한 다음 Enter 키를 누르는 대신 Ctrl-D를 누르면이 솔루션이 실패합니다. – alk

+0

어쨌든'fgets()'ish'\ n'은 제가 놓쳤던 멋진 잡기입니다. :-) – alk

1

어느

  • 는 메모리의 크기

또는

  • -line 일부 유효한 메모리를 가리키고 nbytes를하거나 0NULLnbytesline을 설정합니다. man getline 가입일

:

ssize_t getline(char **lineptr, size_t *n, FILE *stream); 

의 getline는() * lineptr에 텍스트를 포함하는 상기 버퍼의 주소를 저장하는 스트림의 전체 행을 판독한다. 버퍼는 널로 끝나며 개행 문자가 발견되면이를 포함합니다.

* lineptr이 NULL로 설정되고 호출 전에 * n이 0으로 설정된 경우 getline()은 회선을 저장하기위한 버퍼를 할당합니다.

또한 getline()size_t 번째 파라미터 아닌 unsigned long 기대.

^2 이미 1 바이트를 더 할당 한 다음 getline으로 전달할 필요가 없습니다. n 바이트를 할당하고 n을 전달하십시오. n - 1을 전달할 필요가 없습니다.


그리고 항상 반환 결과를 사용하기 전에 malloc()fopen() 등의 관련 시스템 호출에 오류 검사를 추가합니다.

+0

그럼 뭐가 잘못 됐니? – alk

+0

안녕하세요 @alk, getline 호출 인수를 확인해야하지만 이것은 segfault의 원인이 아닙니다. 이 대답은 너무 일반적입니다. – lulyon

+0

이 호출은 확실히 UB를 호출 할 것이고,이 두 번째 호출은 세분화 위반을 포함하여 getline() on을 호출 할 수 있습니다. 또한 이것이 "* general *"가 아닌 느낌이지만 코드에있는 매우 구체적인 버그를 지적합니다. @lulyon – alk

관련 문제