调查Valgrind无效阅读

时间:2016-05-26 00:24:42

标签: c struct valgrind memory-alignment

当我使用project运行时,我收到错误报告。如果我不使用Valgrind,那么该程序看似正常,但我确定Valgrind报告它时出现了问题。

==21286== Invalid read of size 4
==21286==    at 0x404950: fork_pipeline (util.c:296)
==21286==    by 0x403149: execute_pipeline (main.c:177)
==21286==    by 0x4032D5: run_cmd (main.c:221)
==21286==    by 0x403CC3: command (main.c:622)
==21286==    by 0x402B01: main (main.c:933)
==21286==  Address 0x593be68 is 0 bytes after a block of size 24 alloc'd
==21286==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21286==    by 0x4031DD: run_cmd (main.c:204)
==21286==    by 0x403CC3: command (main.c:622)
==21286==    by 0x402B01: main (main.c:933)

违规main.c:204

`struct pipeline *pipe = malloc(chunks->pipes * sizeof *pipe);` 

但我不明白它有什么问题。如果我检查pipes的值,那么它似乎是正确的。周围的代码是:

int run_cmd(const char *cmd) {

    char buffer[2];
    buffer[0] = '|';
    buffer[1] = '\0';
    struct str_list *chunks = list_split(cmd, buffer);
    struct pipeline *pipe = malloc(chunks->pipes * sizeof *pipe);
    pipe->data = malloc(sizeof(char *));
    int i = 0;
    for (i = 0; i < chunks->pipes; i++) {
        pipe[i].data = malloc(sizeof(char *) * BUFFER_SIZE * chunks[i].size);
        int j = 0;
        pipe[i].size = chunks[i].size;
        for (j = 0; j < chunks[i].size; j++) {
            if (chunks[i].argv[j] == NULL) {
                chunks[i].argv[j] = '\0';
                break;
            }
            pipe[i].data[j] = strdup(chunks[i].argv[j]);
            pipe[i].option[0] = chunks[i].option[i];
        }
        pipe[i].data[j] = '\0';
    }
    int status = execute_pipeline(chunks->pipes, pipe);
    return status;
}

如果我查看调试器,那么值看起来不错。我现在的想法是插入断言,以便找到错误出现的位置。

结构有这个声明。

struct str_list {
    char *name;
    int size;
    int pipes;
    char **argv;
    int option[];

};

第二个结构是

struct pipeline {
    char *name;
    int size;
    char **data;
    int option[];
};

更新/编辑

我根据答案更改了代码。

int run_cmd(const char *cmd) {

    char buffer[2];
    buffer[0] = '|';
    buffer[1] = '\0';
    struct str_list *chunks = list_split(cmd, buffer);
    struct pipeline *pipe = malloc(chunks->pipes * sizeof *pipe);
    int i = 0;
    for (i = 0; i < chunks->pipes; i++) {
        pipe[i].data = malloc(sizeof(char **) * BUFFER_SIZE * chunks[i].size);
        int j = 0;
        pipe[i].size = chunks[i].size;
        for (j = 0; j < chunks[i].size; j++) {
            if (chunks[i].argv[j] == NULL) {
                chunks[i].argv[j] = '\0';
                break;
            }
            pipe[i].data[j] = strdup(chunks[i].argv[j]);
            pipe[i].option[0] = chunks[i].option[i];
        }
        pipe[i].data[j] = '\0';
    }
    int status = execute_pipeline(chunks->pipes, pipe);
    return status;
}

仍然无效阅读。

==23103== Invalid write of size 4
==23103==    at 0x403278: run_cmd (main.c:216)
==23103==    by 0x403CB3: command (main.c:621)
==23103==    by 0x402B01: main (main.c:932)
==23103==  Address 0x592e228 is 0 bytes after a block of size 24 alloc'd
==23103==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23103==    by 0x4031DD: run_cmd (main.c:204)
==23103==    by 0x403CB3: command (main.c:621)
==23103==    by 0x402B01: main (main.c:932)
==23103== 
==23104== Invalid read of size 4
==23104==    at 0x404940: fork_pipeline (util.c:296)
==23104==    by 0x403149: execute_pipeline (main.c:177)
==23104==    by 0x4032C5: run_cmd (main.c:220)
==23104==    by 0x403CB3: command (main.c:621)
==23104==    by 0x402B01: main (main.c:932)
==23104==  Address 0x592e228 is 0 bytes after a block of size 24 alloc'd
==23104==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23104==    by 0x4031DD: run_cmd (main.c:204)
==23104==    by 0x403CB3: command (main.c:621)
==23104==    by 0x402B01: main (main.c:932)

第216行:pipe[i].option[0] = chunks[i].option[i];

第204行:struct pipeline *pipe = malloc(chunks->pipes * sizeof *pipe);

2 个答案:

答案 0 :(得分:3)

查看 valgrind 输出,

似乎内存分配为pipe->data 最初,数量由char *类型反映(x86平台上的 ,通常是1个字节,在其他字节上它可能因编译器和平台定义的实现而变化,然后在for循环中,用实际字节调用malloc

删除初次通话中的malloc

pipe->data = malloc(sizeof(char *));

奖励这将消除潜在的内存泄漏

修改

所以data是一个“动态字符串数组”

for循环中:

pipe[i].data = malloc(sizeof(char *) * BUFFER_SIZE * chunks[i].size);

将其更改为:

pipe[i].data = malloc(sizeof(char **) * BUFFER_SIZE * chunks[i].size);

答案 1 :(得分:1)

正如您所知,您在.modal { height: 100%; .modal-dialog { top: 50% !important; margin-top:0; margin-bottom:0; } //keep proper transitions on fade in &.fade .modal-dialog { transform: translateY(-100%) !important; } &.in .modal-dialog { transform: translateY(-50%) !important; } } option中的struct str_list字段使用了灵活的数组。

您必须为您的结构分配占用该空间。我编译并运行了你的代码但是,我改变了:

struct pipeline

struct pipeline {
    char *name;
    int size;
    char **data;
    int *option; // pointer to int
};

这样做,您需要确保为此指针添加struct str_list { char *name; int size; int pipes; char **argv; int *option; // pointer to int }; 次调用。

malloc

我检查了您从未设置struct str_list *chunks = list_split(cmd, buffer); struct pipeline *pipe = malloc(chunks->pipes * sizeof *pipe); pipe->data = malloc(sizeof(char *)); int i = 0; for (i = 0; i < chunks->pipes; i++) { pipe[i].data = malloc(sizeof(char *) * BUFFER_SIZE * chunks[i].size); int j = 0; pipe[i].size = chunks[i].size; for (j = 0; j < chunks[i].size; j++) { if (chunks[i].argv[j] == NULL) { chunks[i].argv[j] = '\0'; break; } pipe[i].option = malloc(sizeof(int) * 10); // However many options... chunks[i].option = malloc(sizeof(int) * 10); // However many options... chunks[i].option[i] = 0; pipe[i].data[j] = strdup(chunks[i].argv[j]); pipe[i].option[0] = chunks[i].option[i]; 字段的util.c函数中的list_split文件,因此我明确初始化了option

在这些更改之后,这些valgrind不再吐出那些错误,但是,你仍然会发现很多内存泄漏。