簡體   English   中英

C 程序在釋放 char 數組中的指針后崩潰 *

[英]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"可能表現得像“明顯”類型的任何其他右值。 唉,雖然1int類型的 integer 文字,但"aaaa"是指針類型const char *的字符串文字 - 它的值不是字符串,而是指針!

就好像當你寫42時, C 給了你一個指向42const int * 這就是“字符串”文字的作用。 這就是 C 非常可悲的一面:(

在 C++ 中,實際上有一個字符串類型( std::string ),您甚至可以使用 C++11 中引入的新語法編寫該類型的文字: "aaaa"sstd::string類型的右值*,而您可以完全按照您對任何其他值類型(如int )的期望分配它們。

由於您已經在思考 C++ 中的內容,也許您接下來可以研究該語言。 與 C 相比,在 C++ 中完成大量基本操作所需的精力要少得多。

*技術上的右值參考

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM