首先,我给出了两个C / C ++函数的代码片段,揭示了C / C ++管理内存分配的不同策略。我在求职面试中被问到这些问题:(
#1
char *func()
{
char *p = "hello world";
return p;
}
#2
char *func()
{
char p[] = "hello world";
return p;
}
人们还能得到字符串" hello world"当func返回时?
这个答案分别是YES和NO
因为在#1,"你好世界"是一个字符串常量。在#2中," hello world"是STACK。但是当以这种方式写作static char p[] = "hello world";
时,答案将是肯定的。
所以,我的问题是 C / C ++如何管理函数的内存分配?
回顾我的面试官告诉我的事情。我记得像STACK / HEAP / DATA SEGMENT / PROGRAM SEGMENT / *这样的东西。我希望任何人都能准确地描述这一点
感谢。
已添加内容
"了解如何在内存中管理代码将有助于程序员编写代码。"这是面试官对我说的话 上面给出的例子用于描述这一点。我想问的是从程序的角度来看如何组织内存段。我期望的答案可能会像
|___________________|
| STACK |
|___________________|
| HEAP |
|___________________|
| DATA SEGMENT |
|___________________|
| PROGRAM SEGMENT |
|___________________|
| ... |
| |
从程序的角度来看,我不确定这样的内存分区是否正确。 (此外,可能存在存储特定类型数据的其他段。)
答案 0 :(得分:1)
第一个是OK,返回的指针指向一个常量文字(但是修改它是未定义的行为,它应该是const
)。
第二个可能导致未定义的行为,它返回一个指向本地变量的指针,该变量将在退出函数后被破坏。
注意:常量文字将存储在DATA-SEGMENT中(在大多数实现中)而不是函数的堆栈中。
答案 1 :(得分:1)
正如所写,你的问题太宽泛而无法完全解决,所以我的目标是在这里解决它的具体内容。
在第一个示例中,我们返回字符串文字的地址,该字符串文字通常存储在进程内存的只读部分的程序段中。您可以在this answer中阅读更多内容。
char *p = "hello world";
return p;
在第二个例子中,我们在堆栈上创建一个字符数组char[]
,并通过制作字符串文字的副本来填充它。每当我们在C
中声明一个非静态数组时,内存总是在堆栈上分配。由于堆栈存储器在函数返回时有效消失,因此指针在函数返回时无效。
char p[] = "hello world";
return p;
在第三个也是最后一个例子中,我们声明了一个静态数组。在函数内部,static
关键字表示变量的生命周期等于整个程序的生命周期。这就是为什么返回一个指向这样一个数组的指针是完全有效的,即使它是一个副本,就像第二个例子一样。
static char p[] = "hello world";
如果您对此类知识感兴趣,我建议this slide deck进一步研究。这是非常实际的,并在访谈的背景下讨论这些问题。