2

以下代码使用堆:

char* getResult(int length) {
    char* result = new char[length];
    // Fill result...
    return result;
}

int main(void) {
    char* result = getResult(100);
    // Do something...
    delete result;
}

所以result必须在某处删除,最好由所有者删除。

据我了解,下面的代码使用了一个名为 VLA 的扩展,它是 C99 的一部分,而不是 C++ 标准的一部分(但受到 GCC 和其他编译器的支持):

char* getResult(int length) {
    char result[length];
    // Fill result...
    return result;
}

int main(void) {
    char* result = getResult(100);
    // Do something...
}

我是否正确假设result在这种情况下仍然分配在堆栈上?

result副本,还是对垃圾内存的引用?上面的代码安全吗?

4

3 回答 3

6

我是否正确假设在这种情况下结果仍然分配在堆栈上?

正确的。VLA 具有自动存储期限。

结果是副本,还是对垃圾内存的引用?上面的代码安全吗?

代码不安全。返回的地址getResult是无效地址。取消引用指针会调用未定义的行为。

于 2013-09-12T17:57:40.407 回答
5

您不能返回它,在C中它将具有自动存储持续时间(一旦您离开范围,对象将无效)并且返回它将调用未定义的行为,来自C99 草案标准部分6.2.4 对象存储持续时间6段:

对于这种确实具有可变长度数组类型的对象,它的生命周期从对象的声明开始,直到程序的执行离开声明的范围。27)如果范围是递归进入的,则该对象的新实例是每次创建。对象的初始值是不确定的。

C++中,我们必须依赖文档,因为在这种情况下它是扩展,并且VLA 上的 gcc 文档说它在作用域结束时被释放:

这些数组的声明与任何其他自动数组一样,但其长度不是常量表达式。存储在声明点分配,并在包含声明的块范围退出时释放。

于 2013-09-12T17:57:31.547 回答
1

当您从 中返回时getResult(),char 数组result将超出范围并与函数调用的堆栈帧一起被释放。如果要保留函数结构,则必须调用malloc并稍后释放内存。

于 2013-09-12T18:03:16.777 回答