[英]Structs containing dynamic char arrays in C
我正在尋找正確的方法來分配和取消分配包含在結構中的動態大小的chars數組(實際上是“ Command”結構的數組)。 以下是在C中解決此問題的正確方法嗎? 在意識到必須一開始將所有數組項都為NULL之前,我遇到了很多問題。 如果不這樣做,則會出現“未分配指針未分配”錯誤。
注意,我必須釋放Command結構數據,因為我正在循環中重用它們。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_NB_ARGS 10
typedef struct {
char* args[MAX_NB_ARGS];
} Command;
void init_commands(Command commands[2]) {
int i;
for (i=0; i<2; ++i) {
int j;
for (j=0; j<MAX_NB_ARGS; ++j) {
// If I don't null these, the free_commands
// function tries to free unallocated memory
// and breaks
commands[i].args[j] = NULL;
}
// Constant of 3 here but in reality variable size
// Idem for the size of the "args" string
for (j=0; j<3; ++j) {
commands[i].args[j] = malloc(5*sizeof(char));
strcpy(commands[i].args[j], "test");
}
}
}
void free_commands(Command commands[2]) {
int i;
for (i=0; i<2; ++i) {
int j=0;
// Do I really clear the second command?
// Debugger shows every args as nil on
// on the second iteration.
while (commands[i].args[j]) {
free(commands[i].args[j]);
commands[i].args[j] = NULL;
++j;
}
}
}
int main () {
Command commands[2];
int i=0;
// Command structs are being reused within the loop
while ((i++)<2) {
init_commands(commands);
puts(commands[1].args[2]); //test print. works.
free_commands(commands);
}
return 0;
}
您在free_commands中崩潰的原因是該函數的參數是未初始化的堆棧變量。 因此,數組args []包含未初始化的指針值。 因此,是的,您需要將它們初始化為NULL才能使free_commands正常工作,否則,您將使用垃圾指針調用free()。 為了避免內存泄漏,您需要為每個malloc()調用free()。
至於其他注釋,您確實需要遍歷每個命令的每個參數。 但是,您的循環結構不正確。 不要在內部循環中使用while循環,您可能會跳過命令0的參數到命令1的參數,也可能超出Commands數組的范圍(如果每個命令的每個參數都分配了一個內存塊,就會發生這種情況)。 它應該是一個從0到MAX_NB_ARGS的for循環。 使用NULL指針調用free()是安全的,如果檢測到NULL,則可以提早退出內部循環。
同樣不要忘記檢查malloc()的返回值。
當我在MacOS X 10.7.2上的valgrind
下運行代碼時,該代碼可以編譯並正常運行,並且我相信剩下的唯一內存就是系統內存。 似乎什么都沒有泄漏。
這與我對代碼的關注一致。 我沒有在代碼中看到泄漏。
如果在malloc()
和free()
調用周圍添加適當的printf()
語句, malloc()
得到:
allocating (0,0) <<test>>
allocating (0,1) <<test>>
allocating (0,2) <<test>>
allocating (1,0) <<test>>
allocating (1,1) <<test>>
allocating (1,2) <<test>>
test
freeing (0,0) <<test>>
freeing (0,1) <<test>>
freeing (0,2) <<test>>
freeing (1,0) <<test>>
freeing (1,1) <<test>>
freeing (1,2) <<test>>
allocating (0,0) <<test>>
allocating (0,1) <<test>>
allocating (0,2) <<test>>
allocating (1,0) <<test>>
allocating (1,1) <<test>>
allocating (1,2) <<test>>
test
freeing (0,0) <<test>>
freeing (0,1) <<test>>
freeing (0,2) <<test>>
freeing (1,0) <<test>>
freeing (1,1) <<test>>
freeing (1,2) <<test>>
您的代碼是干凈的。 但要學習如何進行像這樣的調試打印。
是的,您絕對需要確保在讀取內存之前對其進行了初始化。 您可以通過跟蹤正在使用的條目來跟蹤它,因為您已經為它們寫入了有效的指針(大概需要在結構中添加一個額外的成員才能這樣做),或者通過使用顯式標記未使用的條目來進行管理。 NULL(所以您也已經寫了這些內容)。 兩種技術都有效; 必須使用一個或另一個,因為malloc()
和realloc()
返回的新內存(從理論上講,盡管實際上不是,但calloc()
返回的新內存)沒有正確初始化為null。
(為什么要用calloc()
和理論呢?從理論上講,空指針不必全部為零字節,但是calloc()
內存設置為所有字節零。但是,我還沒有遇到過NULL指針不全是字節為零-這樣的機器上很多代碼都會遇到很多問題。因此,實際上, calloc()
返回空內存,但從理論上講,可能有一台機器不這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.