2012-04-12 1 views
5

Я очень новичок в C и не могу понять, что не так со следующим кодом.Адрес 0x0 не stack'd, malloc'd или (недавно) 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 ближе к концу этого кода.

Кроме того, mychars является двумерный массив, который выглядит следующим образом:

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

Может кто-то пожалуйста, скажите мне, как это исправить? Кроме того, любые указатели на то, как я должен улучшить свой текущий код (особенно с malloc), будут высоко оценены.

Edit: Код для 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; 

} 

EDIT 2 Новый код для str_replace, и главный

Для целей тестирования, я заменил мой метод 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 

Пожалуй, наиболее расстраивает часть этого не зная какой эти недопустимые ошибки чтения являются.

EDIT 3 Я обновил код в центре для цикла, как, например:

 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); 
     } 

И теперь я начинаю получать выход! Однако, после того, как только две итерации, я получаю ошибку сегментации, с Valgrind дает мне целую кучу этого:

==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

В этих двух строках

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

сначала выделить место для result, которые вы затем свободно сразу же после того, как перезаписываются с возвращением str_replace.Эта функция, вероятно, возвращает 0, поэтому ваш fputs терпит неудачу.

BTW, не отбрасывайте возврат malloc, в C это лишнее и может скрыть тот факт, что вы забыли включить прототип.

Редактировать: Ваша функция str_replace полностью ошибочна в управлении памятью. Никогда не возвращайте указатель на локальную переменную, пробел недействителен после того, как вы оставите эту функцию.

+0

Дженс, спасибо, но я до сих пор не знаю, как это исправить. Код для str_replace выше – varatis

+0

@varatis, для 'str_replace' см. Мое редактирование. Для логики вашей программы мне трудно понять, чего вы хотите достичь. Почему вы выделяете что-то внутри цикла, которое вы затем удаляете, и где вы просто используете последнее присвоенное значение в 'fputs'? –

+0

Я пытаюсь прочитать файл в строке за строкой и для каждой строки заменить некоторые символы этой строки строками, указанными mychars – varatis

0

Если NUM равен 0, то result не инициализирована и может быть 0 случайно.

Вы не проверяете результаты своих звонков на malloc(), поэтому отказ может означать, что вы пытаетесь написать указатель NULL.

Где находится mychars?

+0

Они оба объявлены в файле "mychars.h", который импортируется. Но я также заметил, что это работает, за исключением тех случаев, когда я включаю str_replace ... Я собираюсь пойти дальше и добавить этот код – varatis

+0

'malloc', возвращающий' NULL', очень редко в наши дни, особенно с операционными системами, которые реализуют переопределение памяти , – 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