【发布时间】:2021-01-10 01:07:43
【问题描述】:
我刚刚在 format_int 类的 fmt 库中发现了一些东西。它有一个 char 缓冲区成员,这样当您调用类时,堆栈空间会在调用方法的堆栈上分配。您可以从 format_int 返回一个 char * ,即使在类被破坏后它仍然有效。虽然 std::string 也有一个可能返回堆栈内存的 c_str 成员,但 std::string 的析构函数会清除此内存,迫使用户在对象生命周期内使用它。所以相比之下,短暂的 std::string 对象会强制您在对象被破坏之前使用 c_str 的结果,而 format_int 允许您将格式化的缓冲区用于函数的其余部分。
c++ 是否保证堆栈在函数结束之前不会被重用,在调用函数的生命周期内(超出 format_int 对象的生命周期)从 format_int 类中保留缓冲区是否安全?这种行为是我的编译器 (MSVC) 的怪癖吗?
ps。我知道持有内存是非常狡猾的,我只是好奇在现实世界中编译器是否会重用堆栈,或者语言是否禁止这种行为。
【问题讨论】:
-
C++ 中没有堆空间或栈空间的概念。有存储持续时间,可以是静态的、自动的或动态的。静态对象在第一次初始化后在程序的整个生命周期中都存在,自动对象在初始化时开始存在并在范围退出时自动销毁,而动态对象在您释放获得的内存之前一直存在。
-
"在调用方法的栈上分配了栈空间。"你可以在某个地方的文档中链接到这个吗?我一眼看不到那样的东西。 api全部返回
std::stringfmt.dev/latest/api.html -
没有任何保证。一旦对象的生命周期结束,它所包含的任何内容都可能在内存中持续数周,或者在下一个 CPU 周期中消失。
-
Mooing Duck,我想这也是问题的一部分,但正如 Nathan 所说,如果该语言没有真正谈论堆栈或堆,则无法保证。您访问超出其生命周期的东西,坏消息。