3 ms·
Sounds like just a common mistake where people used the "stack" accidentally. Ex: struct someStruct* badfunc(){ struct someStruct toReturn;
by dragontamer 4y ago
Sounds like just a common mistake where people used the "stack" accidentally.
Ex:
struct someStruct* badfunc(){
struct someStruct toReturn;
toReturn.a = foo();
toReturn.b = bar();
return &toReturn;
}
In most people's code, this would probably work...
struct someStruct a = *badfunc();
func2(); // This will overwrite the "toReturn"
// from the last call, but as long as the
// struct was copied before any other function
// call, you're probably fine though in
// undefined-behavior land
-----------------
Either that, or you're talking about strtok (and other non-reentrant functions).
- smarks 4y agoIt was definitely malloc'd memory, as I remember removing free() calls from the callee and adding them to the caller.
- dragontamer 4y agoThat's the old "source/sink" pattern. "Source" functions return a malloc'd pointer. You have to manually call free on it, or pass it to a "sink" function (which internally calls free). In C, this is seen in strdup. C++ took this pattern and formalized it into auto_ptr<>, and later unique_ptr<> when RValue references became a thing in C++11.
- pitched 4y agoI’ve used this before in embedded code to save rom space by not having to include malloc. The stack _is_ the heap! Just have to be very careful about when you can call another function. The best version of this is where you allocate a block on your stack then pass that as a pointer up to the next function to use. The one who owns the memory is the one who allocates it (Rust style?). Or, have the linker allocate global blocks works too.
- drran 4y agoJust bump the stack pointer after call to function and use the allocated memory without risk of overwrite, like alloca() does.
- tpoacher 4y agoQuestion, why would this "probably work"? I would have agreed with your assessment if `a` was used for its one and only purpose before `func2` was called ... but as it stands as soon as `func` is called, the content of `a` will most likely be replaced by garbage (and therefore definitely will not "work" in any reasonable sense of the word), no? Or do you mean something else by "probably work"? (like, in the sense that it will output "something").
- 13of40 4y agoSince func2 doesn't have any parameters, the only thing that calling it will put on the stack is the return address. In fact, if it's the last function call in the code block, even that might get optimized out. The struct should be intact and available via a local variable in func2.
- gsb 4y agoIt's because `a` is not a pointer to the result of badfunc; it is a copy. So the return value of `badfunc` might be overwritten if func2 is non-trivial, but the copy will not.