地址0x0未堆叠,malloc'd或(最近)free'd

时间:2012-04-12 21:21:04

标签: c valgrind

我是C的新手,似乎无法弄清楚以下代码有什么问题。

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对应于以此代码末尾的fput开头的行。

此外,mychars是一个二维数组,如下所示:

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

有人可以告诉我如何解决这个问题吗?此外,我将非常感谢任何有关如何改进当前代码(尤其是使用malloc)的指示。

编辑: 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的新代码和主

出于测试目的,我已将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

也许最令人沮丧的部分是不知道 这些无效的读错误。

编辑3 我已经更新了for循环中心的代码:

        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

3 个答案:

答案 0 :(得分:5)

在这两行中

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

首先为result分配空间,然后通过str_replace的返回覆盖它,然后立即松开。该函数可能会返回0,因此您的fputs会失败。

顺便说一句,不要强制转换malloc,在C中这是多余的,可能会隐藏您忘记包含原型的事实。

编辑:您的str_replace功能在内存处理方面完全错误。永远不要将指针返回到局部变量,在离开函数后空间无效。

答案 1 :(得分:0)

如果NUM为0,则result未初始化,可能偶然为0

您没有检查调用malloc()的结果,因此失败可能意味着您正在尝试写入NULL指针。

mychars在哪里宣布?

答案 2 :(得分:0)

您没有显示mychars的声明方式,但是这一行:

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

看起来它可能只分配一个字节。你也分配了大量的内存,永远不会释放它。在这里:

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

使用malloc分配内存,然后通过在其顶部指定另一个函数的返回值来完全丢弃指向该内存的指针。