我尝试运行这个简单的代码,并预计它会崩溃:
#include <stdio.h>
void setPtrOnTempData(char **ptr) {
char str[] = "AAAA";
*ptr = str;
}
int main() {
char temp[] = "Paras";
temp[3] = 'F';
char *ptr = temp;
ptr++;
ptr[3] = 'F';
printf("%s", ptr); // prints "arFF"
setPtrOnTempData(&ptr);
ptr[0] = 'F';
printf("%s", ptr); // prints "FAAA"
return 0;
}
如果我没记错的话,我这么想的原因是:
但结果是我仍然可以访问一些内存,其中分配了数组,并且我仍然能够更改该数组的数据。
为什么会这样,我的观点错在哪里?谢谢!!
UPD:我很抱歉我的不准确,一开始标题中是“静态”而不是“自动”。
首先,需要澄清的是,
str
中的数组setPtrOnTempData
不是静态分配的。静态分配的变量,或者更准确地说具有“静态存储持续时间”的变量(即使用 static
关键字或在文件范围内)具有完整的程序生命周期。您拥有的是一个具有 自动存储持续时间的变量,其生命周期在
setPtrOnTempData
返回时结束。当您访问生命周期已结束的变量的内存时(正如您在此处所做的那样),它会导致代码中出现未定义的行为。 如果行为未定义,则无法保证您的代码会做什么。它可能会崩溃,可能会表现出奇怪的行为,或者(如您的情况)它可能看起来工作正常。此外,未定义行为的表现方式可能会随着代码看似无关的更改而改变,例如添加未使用的变量或调用
printf
进行调试。
仅仅因为您的代码可能崩溃并不意味着它将会。
您正在 setPtrOnTempData 函数中创建一个本地数组 str[]。但这个数组的作用域仅在函数内。因此,当您分配 *ptr = str 时,您将本地数组 str 的地址分配给 ptr,该地址指向 main 中的 ptr。但是当它返回时被释放时 它可能看起来有效,但它访问无效内存,导致这种奇怪的情况。
void setPtrOnTempData(char **ptr) {
/*ADDED>>>*/ static /*<<<ADDED*/ char str[] = "AAAA";
*ptr = str; // ✓
}
//...
setPtrOnTempData(&ptr);
ptr[0] = 'F'; //✓
//...
一个
static
对象具有
static
生命周期,即使无法通过名称访问它(超出范围),您也可以通过指针访问它。<=>但是您在代码中缺少
static
关键字,如果没有它,您将访问生命周期已结束的变量,这是未定义的行为。