作为一个项目,我正在创建一个学生数据库。但是根据valgrind,我的程序中存在内存泄漏,我不知道为什么。我真的不能说太多:我不明白为什么记忆肯定会丢失。
学生结构:
typedef struct { char student_number[7]; char *first_name; char *last_name; int round_points[6]; } Student;
免责声明:我正在使用gcc选项-std=c99
,因此必须实现自己的strdup()
。
重要的代码段:
char *copy_string(const char *string) { int len = strlen(string); char *copy = calloc(len + 1, sizeof(char)); if (copy == NULL) return NULL; strcpy(copy, string); /* copy[len] = '\0'; */ return copy; } char **parse_one_line_params(const char *one_line, int param_count) { char *copy = copy_string(one_line); if (copy == NULL) return NULL; //copy_start is used to free the copy string in the end char *copy_start = copy; //It is assumed that one_line is of the form COMMAND|SPACE|ARGUMENTS //Move pointer to the first important character copy += 2; const char *separator = " "; char **cOntent= malloc(sizeof(char *) * param_count); if (cOntent== NULL) return NULL; int occurrences = 0; char *delimiter_start; while ((delimiter_start = strstr(copy, separator)) != NULL) { delimiter_start[0] = '\0'; char *sub_string = copy_string(copy); if (sub_string == NULL) return NULL; if (sub_string[0] != '\0') { content[occurrences] = sub_string; } //Since separator is of the length of one copy = delimiter_start + 1; occurrences++; } //param n - 1 will be assigned from the last portion of copy if (occurrences != param_count - 1) return NULL; int last_len = strlen(copy); if (last_len > 0 && copy[last_len - 1] == '\n') copy[last_len - 1] = '\0'; content[occurrences] = copy_string(copy); free(copy_start); return content; } char **deliver_payload(const char *one_line, int param_count) { if (one_line[1] != ' ') { printf("Command was longer than one character.\nPlease see manual for instructions\n"); return NULL; } char **payload = parse_one_line_params(one_line, param_count); if (payload == NULL) { printf("Invalid arguments for given command\n"); return NULL; } return payload; }
有问题的错误是:(记录1至5与以下相同)
==15== 32 bytes in 4 blocks are definitely lost in loss record 5 of 7 ==15== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==15== by 0x400ECA: copy_string (projekti.c:80) ==15== by 0x400F81: parse_one_line_params (projekti.c:106) ==15== by 0x4010B6: deliver_payload (projekti.c:133) ==15== by 0x4019A2: main (projekti.c:301)
301行就是:
char **payload = deliver_payload(one_line, 3);
代码的编辑版本:
char **parse_one_line_params(const char *one_line, int param_count) { char *copy = copy_string(one_line); if (copy == NULL) return NULL; //copy_start is used to free the copy string in the end char *copy_start = copy; //It is assumed that one_line is of the form COMMAND SPACE ARGUMENTS //Move pointer to the first important character copy += 2; const char *separator = " "; char **cOntent= malloc(sizeof(char *) * param_count); if (cOntent== NULL) { free(copy_start); return NULL; } int occurrences = 0; char *delimiter_start; while ((delimiter_start = strstr(copy, separator)) != NULL) { delimiter_start[0] = '\0'; char *sub_string = copy_string(copy); if (sub_string == NULL) { for (int i = 0; i0) { for (int i = 0; i 0 && copy[last_len - 1] == '\n') copy[last_len - 1] = '\0'; content[occurrences] = calloc(last_len + 1, sizeof(char)); strncpy(content[occurrences], copy, last_len); /* content[occurrences] = copy_string(copy); */ free(copy_start); return content; }
编辑valgrind :(在完整输出中,有问题的行是140和118,即calloc)
==15== 13 bytes in 2 blocks are definitely lost in loss record 3 of 7 ==15== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==15== by 0x4011B0: parse_one_line_params (projekti.c:140) ==15== by 0x401236: deliver_payload (projekti.c:153) ==15== by 0x401B22: main (projekti.c:321) ==15== ==15== 27 bytes in 6 blocks are definitely lost in loss record 4 of 7 ==15== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==15== by 0x401075: parse_one_line_params (projekti.c:118) ==15== by 0x401236: deliver_payload (projekti.c:153) ==15== by 0x401BBE: main (projekti.c:337)
最后编辑:我解决了这个特殊问题:我忘了释放主函数中的参数列表,所以最后,我吠叫了错误的树。
你这里有内存泄漏
char **parse_one_line_params(const char *one_line, int param_count){ char *copy = copy_string(one_line); if (copy == NULL) return NULL; /* ... */ char **cOntent= malloc(sizeof(char *) * param_count); if (cOntent== NULL) return NULL;
如果malloc
返回NULL content
,则从函数返回而不释放的内存copy
。malloc
极不可能失败,但是如果您的其余代码以相同的模式编写,则这就是泄漏的来源。
这并不足以“平衡”每个malloc
/ strdup
/ calloc
有一个 free
。您必须跟踪分配内存的位置并释放它,以防您可以访问的最后一个指针超出范围或被覆盖(感谢@Ctx)。