[英]C program crashes after freeing the pointers in an array of char *
我是一名學習 C 的學生,我正在使用 arrays 字符串和 malloc()。
我有以下代碼應該使用動態創建的字符串加載字符串數組(靜態創建)(如果我的術語與我擁有的代碼不一致,請原諒/糾正我)。
問題是,一旦我 go 釋放 memory,我收到以下錯誤: free(): invalid pointer
這是代碼:
#include <stdio.h>
#include <stdlib.h>
#define RAM_SIZE 5
char* ram [RAM_SIZE];
int next_free_cell = 0;
void freeAndNullRam(){
for (int i = 0 ; i < RAM_SIZE ; i++){
printf("%d\n", i);
free(ram[i]);
ram[i] = NULL;
}
}
int main(int argc, const char *argv[])
{
for (int i= 0; i < RAM_SIZE; i++){
ram[i] = (char*)malloc(sizeof(char*)*5);
ram[i] = "aaaa";
}
for (int i= 0; i < RAM_SIZE; i++){
int empty = (ram[i] ==NULL);
if(!empty){
printf("%s\n", ram[i]);
}
}
freeAndNullRam();
for (int i= 0; i < RAM_SIZE; i++){
int empty = (ram[i] ==NULL);
printf("%d\n", empty);
}
return 0;
}
我知道問題肯定出在freeAndNullRam()
function 中(顯然),但我不明白為什么。 我的理解是,在編譯時,創建了一個由 5 個指向 char arrays 的指針組成的數組,但要實際填充數組的單元格,我需要malloc
他們一些 ZCD69B4957F06CD818D7BF3D61980E9 為什么當我釋放數組中的指針時程序會抱怨,但當我給它們 memory 時卻沒有?
謝謝!
ram[i] = "aaaa";
重新分配a[i]
處的指針指向 static memory,丟棄malloc
的結果。 稍后您將這些指針傳遞給free
,它失敗了,因為它們不是*alloc
function 的結果。
使用strcpy
將字符串從 static memory 復制到您分配的目的地。
strcpy(a[i], "aaaa")
這是您的代碼的修改版本,使其更符合慣用 C:
#include <stdio.h>
#include <stdlib.h>
// Create an array of arbitrary size
char* alloc_array(size_t size) {
// calloc() will give you a pre-zeroed (NULL) allocation, malloc() may not
return calloc(size, sizeof(char*));
}
// Clears out all entries in the array, leaving only NULL
void clear_array(char* array, size_t size) {
for (size_t i = 0; i < size; ++i) {
// free(NULL) doesn't do anything, and is easier than a test
free(array[i]);
array[i] = NULL;
}
}
// Clears, then frees the array
void free_array(char* array, size_t size) {
clear_array(array, size);
free(array);
}
int main(int argc, const char *argv[])
{
// Whenever possible use local variables, not global variables
size_t size = 5;
char* entries = alloc_array(size);
for (size_t i = 0; i < size; ++i) {
// Make a copy with strdup() so this can be released with free()
// later on. A string like "..." is static, it was never allocated.
entries[i] = strdup("aaaa");
}
for (size_t i = 0; i < size; i++) {
// Express conditions in the if statment directly
if (entries[i] != NULL) {
printf("%s\n", ram[i]);
}
}
clear_array(entries);
for (size_t i = 0; i < size; i++) {
printf("%d\n", entries[i] != NULL);
}
// Don't forget to release any allocated memory.
free_array(entries);
return 0;
}
你的原始代碼中有很多壞習慣,你應該盡快消除這些壞習慣,這樣這些東西就不會生根發芽。 特別是,全局變量是一個需要避免的巨大問題。
要記住的一件事是,除非某些東西是用malloc()
或類似calloc()
的變體顯式分配的,或者在理解它是以這種方式分配的情況下提供給您的代碼,否則您不應該在其上調用free()
。
不是每個指針都是動態分配的,也不是每個動態分配的指針都是用malloc()
分配的。 因此,一些 C 代碼可能會非常混亂。
C 的語法強烈建議"aaaa"
是一個“字符串”。 人們甚至這樣談論這種語法:他們稱之為“字符串”。 但"aaaa"
並非如此。 它是不幸命名的字符串文字,它不是字符串 - 在 C 和 C++ 中都沒有。 char *
也不是字符串 - 它是指針類型的值。 它用於表示字符串,但它本身不是字符串 - 甚至不接近。
您非常合理地預期"aaaa"
可能表現得像“明顯”類型的任何其他右值。 唉,雖然1
是int
類型的 integer 文字,但"aaaa"
是指針類型const char *
的字符串文字 - 它的值不是字符串,而是指針!
就好像當你寫42
時, C 給了你一個指向42
的const int *
。 這就是“字符串”文字的作用。 這就是 C 非常可悲的一面:(
在 C++ 中,實際上有一個字符串類型( std::string
),您甚至可以使用 C++11 中引入的新語法編寫該類型的文字: "aaaa"s
是std::string
類型的右值*,而您可以完全按照您對任何其他值類型(如int
)的期望分配它們。
由於您已經在思考 C++ 中的內容,也許您接下來可以研究該語言。 與 C 相比,在 C++ 中完成大量基本操作所需的精力要少得多。
*技術上的右值參考
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.