调查 Valgrind 无效读取
Investigate a Valgrind Invalid Read
当我 运行 我的 project with valgrind 我收到错误报告。如果我不使用 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] = '[=12=]';
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] = '[=12=]';
break;
}
pipe[i].data[j] = strdup(chunks[i].argv[j]);
pipe[i].option[0] = chunks[i].option[i];
}
pipe[i].data[j] = '[=12=]';
}
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] = '[=15=]';
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] = '[=15=]';
break;
}
pipe[i].data[j] = strdup(chunks[i].argv[j]);
pipe[i].option[0] = chunks[i].option[i];
}
pipe[i].data[j] = '[=15=]';
}
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);
查看 valgrind 输出,
似乎内存分配最初pipe->data
,数量反映在类型char *
(在 x86 平台上,它通常是 1 个字节,在其他情况下它可能因编译器和平台定义的实现而异),然后在 for
循环中,用实际字节调用 malloc
。
删除 malloc
初始调用。
pipe->data = malloc(sizeof(char *));
奖励 这将消除潜在的内存泄漏
编辑
所以 data
是 "dynamic array of strings"
在 for
循环中:
pipe[i].data = malloc(sizeof(char *) * BUFFER_SIZE * chunks[i].size);
将其更改为:
pipe[i].data = malloc(sizeof(char **) * BUFFER_SIZE * chunks[i].size);
如您所见,您在 struct str_list
和 struct pipeline
.
中为 option
的字段使用了灵活的数组
您必须在为您的结构分配时考虑 space。我已经编译并运行你的代码,但是,我改变了:
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] = '[=12=]';
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];
我在 list_split
函数中检查了 util.c
文件,您从未设置 option
字段,所以我显式初始化 chunks[i].option[i] = 0
.
在这些更改之后,那些 valgrind 不再吐出那些错误,但是,您仍然有相当多的内存泄漏显示。
当我 运行 我的 project with valgrind 我收到错误报告。如果我不使用 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] = '[=12=]';
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] = '[=12=]';
break;
}
pipe[i].data[j] = strdup(chunks[i].argv[j]);
pipe[i].option[0] = chunks[i].option[i];
}
pipe[i].data[j] = '[=12=]';
}
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] = '[=15=]';
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] = '[=15=]';
break;
}
pipe[i].data[j] = strdup(chunks[i].argv[j]);
pipe[i].option[0] = chunks[i].option[i];
}
pipe[i].data[j] = '[=15=]';
}
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);
查看 valgrind 输出,
似乎内存分配最初pipe->data
,数量反映在类型char *
(在 x86 平台上,它通常是 1 个字节,在其他情况下它可能因编译器和平台定义的实现而异),然后在 for
循环中,用实际字节调用 malloc
。
删除 malloc
初始调用。
pipe->data = malloc(sizeof(char *));
奖励 这将消除潜在的内存泄漏
编辑
所以 data
是 "dynamic array of strings"
在 for
循环中:
pipe[i].data = malloc(sizeof(char *) * BUFFER_SIZE * chunks[i].size);
将其更改为:
pipe[i].data = malloc(sizeof(char **) * BUFFER_SIZE * chunks[i].size);
如您所见,您在 struct str_list
和 struct pipeline
.
option
的字段使用了灵活的数组
您必须在为您的结构分配时考虑 space。我已经编译并运行你的代码,但是,我改变了:
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] = '[=12=]';
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];
我在 list_split
函数中检查了 util.c
文件,您从未设置 option
字段,所以我显式初始化 chunks[i].option[i] = 0
.
在这些更改之后,那些 valgrind 不再吐出那些错误,但是,您仍然有相当多的内存泄漏显示。