在堆或堆栈上分配的动态创建的字符串 - C

Dynamically created string allocated on heap or stack - C

本文关键字:动态 创建 字符串 分配 堆栈      更新时间:2023-10-16

上下文

我正在尝试在不分配堆内存的情况下获取 C++ C 字符串,并在测试中遇到了这个问题:

#include <stddef.h>
#include <stdlib.h>
char* get_empty_c_string(size_t length) {
char buffer[length];
char *string = buffer;
for (size_t i = 0; i ^ length; i++) *(string + i) = '';
return string;
}
int main(void) {
char *string = get_empty_c_string(20u); // Allocated on heap?
// or stack?
return 0;
}

问题

返回的 C 字符串是在堆上还是在堆栈上分配?

据我所知:

  • 堆分配发生在callocmalloc&reallocC标准函数或new&new[]C++关键字。

  • 大多数其他情况下的堆栈分配。

数组buffer是一个可变长度数组(VLA(,这意味着它的大小是在运行时确定的。 作为函数的局部变量驻留在堆栈上。 然后,指针string指向该数组,并返回该指针。 由于返回的指针指向超出范围的局部堆栈变量,因此尝试使用该指针将调用未定义的行为。

另请注意,VLA 是仅限 C 的功能。

在标准C++中无法获取自动存储持续时间的运行时大小的内存(通常映射到堆栈内存(。

因此,无法在堆栈上获得任何长度的适当字符串。您只能分配最大大小的缓冲区,并在程序中使用最大长度的字符串。(类似的事情通常由所谓的短字符串优化std::string完成。

此外,不能从函数返回具有自动存储持续时间的变量的指针或引用。当函数返回时,变量被销毁,指针/引用变得无效。在函数返回之前,您只能使用堆栈分配。但是,您可以按值返回变量。

正如@PaulMcKenzie指出的,get_empty_c_string()的实现将无法编译: 本质上,作为函数的临时/实例变量的数组需要在编译之前为它们定义静态大小。这是因为该内存量在函数调用时被推送到堆栈上

我可以看到您正在尝试将动态内存分配作为函数本身的一部分,这就是您需要这样的堆分配器的原因。