2012-04-12 1 views
5

저는 C 언어에 익숙하지 않아 다음 코드에 무엇이 잘못되었는지 알 수 없습니다.주소 0x0은 stack'd가 아니며 malloc되었거나 (최근에) free'd가되었습니다

int main() { 
    char filen[] = "file.txt"; 
    FILE *file = fopen (filen, "r"); 
    if (file != NULL) 
    { 
     char line [ 128 ]; 
     while (fgets (line, sizeof line, file) != NULL) /* read a line */ 
     { 
      int i; 
      char *result; 
      for(i=0; i< NUM;i++) 
      { 
       char *rep; 
       rep = (char *) malloc (sizeof(mychars[i][0])); 
       strcpy(rep, mychars[i][0]); 
       char *with; 
       with = (char *) malloc (sizeof(mychars[i][1])); 
       strcpy(with, cgichars[i][1]); 
       result = (char *) malloc (sizeof(char) * 128); 
       result = str_replace(line, rep, with); 
      } 


      fputs(result, stdout); 
     } 
    } 
    fclose (file); 


    return 0; 
} 

Valgrind의 날이 오류를주고있다 :

==4266== Invalid read of size 1 
==4266== at 0x4C286D2: __GI_strlen (mc_replace_strmem.c:284) 
==4266== by 0x5118A8D: fputs (iofputs.c:37) 
==4266== by 0x400A0F: main (repl.c:35) 
==4266== Address 0x0 is not stack'd, malloc'd or (recently) free'd 

repl.c이 코드의 끝을 향해 fputs로 시작하는 줄에 해당합니다.

char *mychars[NUM][2] = { 
    "a", "97", 
    "b", "98", 
    .... 

사람이 어떻게이 문제를 해결하는 방법 말해 주시겠습니까 :

또한

, mychars은 다음과 같습니다 두 차원 배열은? 또한, 현재 코드를 개선해야하는 방법 (특히 malloc을 사용하는 방법)에 대한 모든 정보는 많은 도움이 될 것입니다.

편집 : 않는 str_replace 않는 str_replace에 대한

char *str_replace(char *str, char *orig, char *rep) { 
    char buffer[4096]; 
    char *p; 

    if(!(p = strstr(str, orig))) 
    return NULL; 

    strncpy(buffer, str, p-str); 
    buffer[p-str] = '\0'; 
    sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig)); 

    return buffer; 

} 

편집 2 새로운 코드에 대한 코드 및 테스트 목적으로

주, 나는 대체했습니다 여기에있는 한 내 않는 str_replace 방법 :

What is the function to replace string in C?

차 내 주요 약간 변경 :

int main() { 
    static const char filen[] = "file.txt"; 
    FILE *file = fopen (filen, "r"); 
    if (file != NULL) 
    { 
     char line [ 128 ]; 
     while (fgets (line, sizeof line, file) != NULL) /* read a line */ 
     { 
      int i; 
      char *result; 
      for(i=0; i< NUM;i++) 
      { 
       char *rep; 
       rep = (char *) malloc (sizeof(mychars[i][0])); 
       strcpy(rep, mychars[i][0]); 
       char *with; 
       with = (char *) malloc (sizeof(mychars[i][1])); 
       strcpy(with, mychars[i][1]); 
       result = str_replace(line, rep, with); 
      } 


      fputs(result, stdout); 
     } 
    } 
    fclose (file); 


    return 0; 
} 

하지만 난 여전히 아마도 이것의 가장 실망스러운 부분은 이러한 잘못된 읽기 오류가 무엇을 모르고있다

==6730== Invalid read of size 1 
==6730== at 0x4C286D2: __GI_strlen (mc_replace_strmem.c:284) 
==6730== by 0x5118A8D: fputs (iofputs.c:37) 
==6730== by 0x400995: main (repl.c:29) 
==6730== Address 0x0 is not stack'd, malloc'd or (recently) free'd 

을 얻고있다.

 int i; 
     char* result; 
     result = &line[0]; 
     for(i=0; i< NUM_CGICHARS;i++) 
     { 
      char *rep; 
      rep = (char *) malloc (sizeof(char)); 
      strcpy(rep, cgichars[i][1]); 
      char *with; 
      with = (char *) malloc (sizeof(char)*3); 
      strcpy(with, cgichars[i][0]); 
      result = str_replace(result, rep, with); 
      fputs(result, stdout); 
      free(rep); 
      free(with); 
     } 

을 그리고 지금은 출력을 얻을 시작 했어 :

EDIT 3 내가 같은 루프의 중앙에 코드를 업데이트했습니다! 그러나,이 반복 후에, 나는 Valgrind의 날이의 전체 무리를주는, 세그먼트 오류를 ​​얻을 : result가 초기화되지 않은이고 우연히 0 수 있습니다 다음, 0

==9130== Invalid read of size 1 
==9130== at 0x4C286D2: __GI_strlen (mc_replace_strmem.c:284) 
==9130== by 0x5118A8D: fputs (iofputs.c:37) 
==9130== by 0x4009DF: main (teststep1.c:27) 
==9130== Address 0x0 is not stack'd, malloc'd or (recently) free'd 

답변

5

당신 다음 느슨한 직후 str_replace의 복귀로 덮어 써서.이 함수는 0을 반환하므로 fputs이 실패합니다.

사실, malloc의 결과를 던지지 마십시오.이 메시지는 불필요하며 프로토 타입을 포함하지 않았다는 사실을 숨길 수 있습니다.

편집 :str_replace 기능은 메모리 처리에서 완전히 잘못되었습니다. 포인터를 지역 변수에 반환하지 마십시오. 함수를 떠난 후에는 공간이 유효하지 않습니다.

+0

Jens, 고마워요.하지만이 문제를 해결하는 방법에 대해서는 아직 모릅니다. str_replace에 대한 코드는 – varatis

+0

@varatis, str_replace에 대해서는 제 편집을 참조하십시오. 프로그램의 논리를 위해, 나는 당신이 달성하기를 원하는 것을 이해하기가 어렵습니다. 왜 당신은 지울 루프 안에서 무언가를 할당하고 있으며,'fputs'에서 마지막으로 할당 된 값을 사용하는 곳은 무엇입니까? –

+0

줄 단위로 파일을 읽으려고하고 각 줄마다 mychars에서 지정한 문자열로 해당 줄의 특정 문자를 바꿉니다. – varatis

0

NUM합니다.

malloc()으로 전화 한 결과를 확인하지 않으므로 오류로 인해 NULL 포인터에 쓸 수 있습니다.

mychars는 어디에서 확인할 수 있습니까? 이 두 줄

  result = (char *) malloc (sizeof(char) * 128); 
      result = str_replace(line, rep, with); 

먼저 result을위한 공간을 할당에서

+0

두 파일 모두 가져 오는 "mychars.h"파일에서 선언됩니다. 그러나 나는 str_replace를 포함 할 때를 제외하고이 함수가 작동한다는 것을 알았습니다. 나는 계속해서 그 코드를 추가 할 것입니다. – varatis

+0

'NULL'을 반환하는'malloc'은 요즘 매우 드뭅니다. 특히 메모리 오버 커밋을 구현하는 운영 체제의 경우 . – dreamlax

+0

@dreamlax : wtf !? – James

0

당신은 선언하는 방법을 mychars 보여 주지만,이 라인하지 않습니다 : 그것은 아마 하나의 바이트를 할당처럼

rep = (char *) malloc (sizeof(mychars[i][0])) 

보인다. 또한 많은 양의 메모리를 할당하고 결코 해제하지 마십시오. 그리고 여기 :

result = (char *) malloc (sizeof(char) * 128); 
result = str_replace(line, rep, with); 

당신은 malloc를 사용하여 메모리를 할당 한 후 완전히의 맨 위에 또 다른 함수의 반환 값을 할당하여 해당 메모리에 대한 포인터를 폐기합니다.

+0

dreamlax, 다시 한 번 도움을 주셔서 감사합니다. 그러나이 문제를 수정/변경하려면 어떻게해야합니까? – varatis