問題:我有我目前正在測驗
的功能 (add_filename()和)。init_filename()他們必須將檔案中的行讀取到動態分配的字串陣列中。Init 啟動陣列,然后 Add 添加新元素。這兩個函式都回傳一個指向陣列開頭的指標。我已采取所有必要的預防措施以確保realloc()不會丟失指標。還有一些標志表明記憶體分配有問題。我釋放了一切(我能想到的)。然而,它仍然在泄漏......
代碼:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **add_filename(char **filenames, char *new_file, int *file_num, int *flag);
char **init_filename(char *new_file, int *flag);
int main() {
FILE *file;
file = fopen("file.txt", "r");
char *buffer = 0;
size_t buf_size = 0;
size_t chars = 0;
int file_num = 0, check = 1;
// char ch;
if (file != NULL) {
char **files;
while ((int)(chars = getline(&buffer, &buf_size, file)) > 0) {
if (!file_num) {
files = init_filename(buffer, &check);
file_num ;
}
files = add_filename(files, buffer, &file_num, &check);
printf("files = %s", files[file_num - 1]);
free(buffer);
buffer = NULL;
if (check == 0) {
printf("we have problems\n");
break;
}
}
free(buffer);
buffer = NULL;
fclose(file);
if (files) {
for (int i = 0; i < file_num; i ) {
free(files[i]);
}
}
}
return 0;
}
char **init_filename(char *new_file, int *flag) {
char **init = malloc((1) * sizeof(char*)); //
if (init) {
init[0] = malloc((strlen(new_file) 1) * sizeof(char));
if (!init[0])
*flag = 0;
} else {
*flag = 0;
}
return init;
}
char **add_filename(char **filenames, char *new_file, int *file_num, int *flag) {
char **temp = realloc(filenames, (*file_num 1) * sizeof(char *));
if (temp) {
filenames = temp;
filenames[*file_num] = malloc((strlen(new_file) 1) * sizeof(char));
if (filenames[*file_num] != NULL) {
strcpy(filenames[*file_num], new_file);
*file_num = *file_num 1;
} else {
*flag = 0;
}
} else {
*flag = 0;
}
return filenames;
}
這是 valgrind 的輸出:
==5881== HEAP SUMMARY:
==5881== in use at exit: 32 bytes in 1 blocks
==5881== total heap usage: 15 allocs, 14 frees, 6,285 bytes allocated
==5881==
==5881== 32 bytes in 1 blocks are definitely lost in loss record 1 of 1
==5881== at 0x484DCD3: realloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==5881== by 0x1094E2: add_filename (test.c:72)
==5881== by 0x109335: main (test.c:23)
==5881==
==5881== LEAK SUMMARY:
==5881== definitely lost: 32 bytes in 1 blocks
==5881== indirectly lost: 0 bytes in 0 blocks
==5881== possibly lost: 0 bytes in 0 blocks
==5881== still reachable: 0 bytes in 0 blocks
==5881== suppressed: 0 bytes in 0 blocks
==5881==
==5881== For lists of detected and suppressed errors, rerun with: -s
==5881== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
這是 ASan 的輸出:
Direct leak of 32 byte(s) in 1 object(s) allocated from:
#0 0x7f200c4b4c18 in __interceptor_realloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:164
#1 0x5591559a2a8a in add_filename /home/licht/Documents/Knowledge/school21/inProgress/C3_SimpleBashUtils-0/src/test.c:72
#2 0x5591559a2631 in main /home/licht/Documents/Knowledge/school21/inProgress/C3_SimpleBashUtils-0/src/test.c:23
#3 0x7f200c029d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
SUMMARY: AddressSanitizer: 32 byte(s) leaked in 1 allocation(s).
uj5u.com熱心網友回復:
代碼中存在多個問題:
files必須初始化為NULL:init_filename如果檔案不為空,它將被初始化,但在結束時釋放時將保持未初始化并導致未定義的行為main()(如果files最終按應有的方式釋放)。- 你應該去掉
getline(). - 不需要
init_filename(): 傳遞一個空指標到realloc()是允許的,并且在這種情況下realloc會表現得像。malloc - 第一個檔案名在陣列中添加了兩次:一次是
init_filename,另一次是add_filename - 回圈內部不需要釋放
buffer:它將被重用于下一行并根據需要重新分配。 - 分配字串的副本應該
strdup()在一次呼叫中安全地結合記憶體分配和字串復制。該函式是 C23 C 標準的一部分,并且在 POSIX 系統上已經使用了幾十年。在不提供它的遺留系統上很容易實作。毫無疑問,它在您的系統上可用,因為您依賴getline. - 最后但同樣重要的是:您忘記釋放
files,這可能是您觀察到的泄漏。
這是修改后的版本:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **add_filename(char **filenames, const char *new_file,
int *file_num, int *flag);
int main() {
FILE *file;
char *buffer = NULL;
size_t buf_size = 0;
char **files = NULL;
int file_num = 0, check = 1;
file = fopen("file.txt", "r");
if (file == NULL) {
fprintf(stderr, "cannot open %s: %s\n", "file.txt", strerror(errno));
return 1;
}
while (getline(&buffer, &buf_size, file) > 0) {
// clear the trailing newline if any
buffer[strcspn(buffer, "\n")] = '\0';
files = add_filename(files, buffer, &file_num, &check);
if (check == 0) {
printf("filename could not be inserted: %s\n", buffer);
break;
}
printf("file = %s\n", files[file_num - 1]);
}
free(buffer);
fclose(file);
if (files) {
for (int i = 0; i < file_num; i ) {
free(files[i]);
}
free(files);
}
return 0;
}
char **add_filename(char **filenames, const char *new_file,
int *file_num, int *flag) {
int num = *file_num;
char **temp = realloc(filenames, (num 1) * sizeof(*filenames));
if (temp) {
filenames = temp;
filenames[num] = strdup(new_file);
if (filenames[num] != NULL) {
// update the filename count and set the success flag
*file_num = num 1;
*flag = 1;
} else {
// could not allocate new string: clear flag
*flag = 0;
}
} else {
// realloc failed: clear flag to indicate failure
*flag = 0;
}
return filenames;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/532243.html
標籤:C内存泄漏重新分配
