c - 这段c代码中的奇怪行为是什么?

标签 c heap-memory stack-memory

我不清楚以下两段代码如何显示不同的行为:

代码:

#include <stdio.h>

void set(char** addr) {
  char* str = "testa";
  *addr = str;
}

void _set(char*** addr) {
  char* arr[] = {"testb"};
  *addr = arr;
}

int main() {
  char* a;
  set(&a);
  printf("'%s'\n", a);
  printf("'%s'\n", a);

  char** b;
  _set(&b);
  printf("'%s'\n",b[0]);
  printf("'%s'\n",b[0]);
}

输出:

testa
testa
testb
testb

当我删除第一位,即种皮部分时,代码是:

void _set(char*** addr) {
  char* arr[] = {"testb"};
  *addr = arr;
}

int main() {
  char** b;
  _set(&b);
  printf("'%s'\n",b[0]);
  printf("'%s'\n",b[0]);
}

输出:

'testb'
'UH▒▒AWE1▒AVAUATSH▒▒8▒E▒'

最佳答案

您遇到内存损坏。 main() 中的代码引用堆栈上的内存,当调用新函数时,该内存可能会被损坏。 “testb”本身并未损坏,但 arr 已损坏(包含字符串文字“testb”的地址的位置)

如果您进行以下更改,它将起作用:

char* arr[] = {"testb"}; /* Make arr global to fix the bug */

void _set(char*** addr) {
   /* alternatively, you could make arr static here, static char* arr... */    

   *addr = arr;
}

经过足够的挖掘,应该可以解释为什么它在第一种情况下有效,但在第二种情况下不起作用,并且它将是确定性和可重复的。例如,试试这个:

void _set(char*** addr) {
  char pad[3]; // <-- Insert a 3 byte stack variable
  char* arr[] = {"testb"};
  *addr = arr;
}

你现在应该看到一些不同的东西(嗯,第二行看起来熟悉吗?):

'testb'
''%s'
'

关于c - 这段c代码中的奇怪行为是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20693606/

相关文章:

c - 操作系统使用堆来实现动态内存管理的数据结构?

elasticsearch - 在具有2GB RAM的计算机上引导elasticsearch

c++ - 使用基于堆的数据调用将堆栈对象作为参数的函数

.net - .net 中的堆栈和堆内存分配

c - C 函数中的变量参数

c - 服务器架构之谜,C编程

c++ - 程序在 x64 中崩溃,在 Win32 中工作正常

c - FFTW - fftw_alloc() 是否必要?

c - 发送带有二进制 null '\0' 的字符串

c++ - 堆和栈内存是如何管理、实现和分配的