-2

请考虑以下 C++ 代码片段。我将对 char * 的引用作为函数的参数传递。

void name(char **str){
    *str=(char *)"JUSTFORFUN";
}


int main(int argc, const char * argv[])
{
    char *test;
    name(&test);
    cout<<test; //Prints "JUSTFORFUN"
    //delete(test); //Throws error "pointer being freed was not allocated"
    return 0;
}

我认为分配用于在函数名()中存储“JUSTFORFUN”的内存是在堆栈上分配的。因此,当控件超出 name() 时,与 (char *)"JUSTFORFUN" 关联的内存应该已被编译器释放。我的问题是为什么我在打印测试时仍然得到正确的输出?它不应该打印一个垃圾值吗?

当我为 int 做类似的事情时。我得到了预期的结果。

void nameint(int **value){
    int val=5;
    *value=&val;
}

int main(int argc, const char * argv[])
{
    int *val;
    nameint(&val);
    cout<<*val; //Prints a junk value 1073828160    
    return 0;
}

为什么 int 和 char * 的行为有区别?

4

4 回答 4

1

字符串文字"JUSTFORFUN"不存储堆栈中——它具有静态存储持续时间。尽管只出现在函数内部name,但字符串文字本身并不是该函数的本地(没有字符串文字——它们都有静态存储持续时间)。

因此,第一个程序的行为实际上是很好定义的。name返回后,val包含具有静态存储持续时间的字符串文字的地址,然后您将打印该地址。

在您的第二个程序中,您将返回函数本地的 int 的地址。函数返回后,它int不再存在,因此使用它会产生未定义的行为——在典型情况下,它可能会打印出当前位于该地址的位的任何值,但不能保证它会做什么.

于 2013-06-23T05:49:10.813 回答
1

“JUSTFOFUN”未在堆栈上分配。它与程序的其余静态数据一起存储。该name函数在堆栈上存储一个指针。该指针指向静态数据。

但是,您的 int存储在堆栈中。您的nameint函数返回一个指向堆栈上该位置的指针。做这样的事情会导致你的程序很快崩溃。

于 2013-06-23T05:49:41.433 回答
0

我认为分配用于在函数名称()中存储“JUSTFORFUN”的内存是在堆栈上分配的

不,不是。字符串文字隐含地具有static存储持续时间。它们的生命周期就是程序的生命周期。没有delete,您的第一个程序是正确的。

引发错误“未分配被释放的指针”

当然可以,因为您没有使用new.

int为什么和的行为有区别char *

因为这就是语言的定义方式。在第二个程序中,int 确实具有自动存储持续时间(它是用您的话“分配的堆栈”),因此在其封闭范围之外使用它的地址(这是这里的函数)会调用未定义的行为。

于 2013-06-23T05:50:46.340 回答
0

两种不同的情况:

在字符串的情况下,您没有分配任何内存,因为原始字符串(例如const char* x = "sdfsdf")保存在可执行文件的 .data 部分中,因此您可以将其视为随程序加载的静态不可变数据(根本没有内存分配分配!)

在第二种情况下val,在函数堆栈上分配,然后在函数返回时变为无效。

于 2013-06-23T05:50:00.563 回答