c - 当我 malloc 错误的内存量时,为什么 C 不会崩溃

标签 c memory malloc valgrind heap-memory

我正在学习 C,我想知道为什么下面的代码没有崩溃,我只是使用 Valgrind 才发现这个问题。

void push(char *element){
  FILE *file = fopen("stack.db", "w");
  int rc = fwrite(element, sizeof(element), 1, file);
  if (file) fclose(file);
}

void top() {
  char *top_element = malloc(sizeof(char));
  FILE *file = fopen("stack.db", "r+");
  int rc = fread(top_element, sizeof(char), 1, file);
  printf("Top element: %s", top_element);
}

int main(int argc, char *argv[]) {
  char action = argv[1][0];
  switch (action) {
    case 'p':
      printf("pushing element to stack\n");
      push(argv[2]);
      break;
    case 't':
      top();
      break;
    default:
      printf("die\n");
  }
  return 0;
}

首先我调用push() 并将argv[2] 写入文件。然后我调用 top();我从malloc得到一 block 内存,sizeof char,分配给top_element。但是,这应该是 sizeof char*,所以我实际上调用了 malloc(1),而我本应该调用 malloc(8)。此代码有效,我只在使用 Valgrind 时才发现错误。

我的问题是,当我分配给 top_element 的内存大小太小时,它如何工作?

最佳答案

不对,应该是sizeof(char)。您需要一段足够长的内存来存储单个字符; malloc(sizeof(char)) 返回一个指向它的指针。 malloc(sizeof(char*)) 将返回一个指向足够内存的指针来存储 char*。您可以将 malloc(T * n) 视为将 T* 返回给 n T

我怀疑 Valgrind 提示 printf 将读取超出 char* top_element 所表示的字符串的末尾 ,因为它是不是零终止。如果你想从文件中读取一个 n 字节的字符串,你确实需要 n + 1 字节的内存,因为你需要考虑 \0 你应该放在最后。然而,并不是所有的 char* 都代表字符串,所以在很多情况下这种用法是可以的。在你的情况下,它真的应该是:

// Allocate zeroed memory
char *top_element = calloc(2, sizeof(char));

if (top_element)
{
  FILE *file = fopen("stack.db", "r+");
  int rc = fread(top_element, sizeof(char), 1, file);
  printf("Top element: %s", top_element);
  free(top_element);
}
else
{
  // Out of memory!
}

关于c - 当我 malloc 错误的内存量时,为什么 C 不会崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21628674/

相关文章:

c - 获取 char* 的子串

c - 这个合并排序有什么问题?

java - 与 Java 中的 GCHandle.Alloc() 等效的代码?

C - malloc 大小小于参数大小的 strcpy

c - 生成文件不工作? 'Nothing to be done for ' 生成文件'

c - 段错误(核心转储),无编译错误

C 程序内存使用 - 报告的内存多于分配的内存

java - 弱引用中的强引用

c - 将 C 翻译成 Golang。如何分配内存以匹配 C?

c - Mallocing 二维数组,尝试打印字符串后崩溃