0

I just came across a something from the fmt library in the format_int class. It has a char buffer member such that when you invoke the class stack space is allocated on the stack in the calling method. You can return a char * from format_int and it remains valid even after the class has been destructed. While std::string also has a c_str member which may return stack memory, the destructor for std::string clears this memory forcing the user to make use of it during the object lifetime. So in comparison short lived std::string objects force you to use the results of c_str before the object is destructed, while format_int lets you use the formatted buffer for the remainder of the function.

Does c++ guarantee that the stack will not be reused until the end of the function, is it safe to hold onto the buffer from the format_int class for the lifetime of the calling function (beyond the lifetime of the format_int object)? Is this behavior a quirk with my compiler (MSVC)?

ps. I get that holding onto the memory is pretty sneaky, I'm just curious if in the real world a compiler would reuse the stack, or if the language forbids that behavior.

Medran
  • 433
  • 3
  • 10
  • 2
    There is no concept of heap space or stack space in C++. There is storage duration, which can be static, automatic, or dynamic. Static objects live for the life of the program after their first initialization, automatic objects come to life when initialized and are automatically destroyed at scope exit, and dynamic objects live until you release the memory you acquired. – NathanOliver Sep 23 '20 at 19:05
  • " stack space is allocated on the stack in the calling method." Can you link to this in the docs somewhere? I don't see anything like that at a glance. The apis all return `std::string` https://fmt.dev/latest/api.html – Mooing Duck Sep 23 '20 at 19:05
  • 3
    There are no guarantees. Once the object's lifetime has ended, whatever it contained could last in memory for weeks or be gone the very next CPU cycle. – user4581301 Sep 23 '20 at 19:06
  • Related: [Can a local variable's memory be accessed outside its scope?](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – user4581301 Sep 23 '20 at 19:08
  • Mooing Duck, I suppose that's also part of the question, but as Nathan says if the language doesn't really talk about stack or heap there are no guarantees. Your accessing something beyond its lifetime, bad news. – Medran Sep 23 '20 at 20:28
  • user458... accessing the memory from a local function variable is a pretty common mistake beginner programmers make. I think its very different from c++ where you can safely return a pointer/reference to a member and use it up until the object expires. C++ makes the guarantee that the object will live at least as long as the expression, in C there is no concept as objects per say. – Medran Sep 23 '20 at 20:32
  • Going to chalk this one up to not guaranteed behavior, but compilers may not be likely to reuse the stack after the temporary object is destroyed. – Medran Sep 23 '20 at 20:33
  • Mooing Duck, its not listed in the api's, but if you read the source the format_int class has a buffer as a member where it does its work. The address of the buffer is returned when you call the c_str method. When you call format_int (construct it) the format_int object takes up stack space on the calling function. But it appears the stack itself is not guaranteed behavior, its just the way most compilers allocate memory for locals. – Medran Sep 23 '20 at 20:44
  • @Medran Use `@username` to reply to people, otherwise they won't get notifications and won't reply. – HolyBlackCat Sep 24 '20 at 19:06

1 Answers1

2

You can return a char * from format_int and it remains valid even after the class has been destructed.

It does not. The pointer returned from format_int::c_str is invalidated when the format_int object is destroyed. This is similar to std::basic_string::c_str.

does the stack space for temporary objects get reused?

It can be reused.

vitaut
  • 49,672
  • 25
  • 199
  • 336