| ▲ | jcalvinowens 3 hours ago |
| > As local variables are typically hidden from the ABI, this approach has a marginal impact on it. I'm skeptical this is workable... it's pretty common in systems code to take the address of a local variable and pass it somewhere. Many event libraries implement waiting for an event that way: push a pointer to a futex on the stack to a global list, and block on it. They address it explicitly later: > Although simply modifying types of a local variable doesn’t normally impact the ABI, taking the address of such a modified type could create a pointer type that has an ABI mismatch That breaks a lot of stuff. The explicit annotations seem like they could have real value for libraries, especially since they can be ifdef'd away. But the general stack variable thing is going to break too much real world code. |
|
| ▲ | menaerus 2 hours ago | parent | next [-] |
| I don't understand this example: you're taking an address of local-scope stack object, storing it into a global list, and then use this address elsewhere in the code, possibly at different time-point, to manipulate with the object? I am obviously missing something because this cannot work unless this object lives on the stack of main(). |
| |
| ▲ | jcalvinowens 2 hours ago | parent | next [-] | | The best example I know of off the top of my head is wait_event() in Linux. So long as the thread is guaranteed not to exit while blocked, you know its stack, and therefore the object allocated on it, must continue to exist. So, as long as there is no way to wake the thread except by kicking that object, the memory backing it is guaranteed to continue to exist until that object is kicked. You do have to somehow serialize the global data structure lookup (e.g. lock/dequeue/unlock/kick), if multiple threads can find and kick the object concurrently that's unsafe (the thread might exit between the first and subsequent kicks). Generally that's true, even in pthread userspace: while there are some obvious artificial counterexamples one can construct, real world code very rarely does things like that. | | |
| ▲ | menaerus an hour ago | parent [-] | | Ok, I see, thanks for the example. Is this technique used to avoid the potential runtime performance cost because one would otherwise need to keep that object elsewhere/heap and not on a stack? Or is the problem definition something else? | | |
| ▲ | jcalvinowens an hour ago | parent [-] | | It's just mechanically simpler that way. If the wakee thread dynamically allocated the object, it would have to free it after being woken: may as well let the compiler do that automatically for us. |
|
| |
| ▲ | jandrese 2 hours ago | parent | prev [-] | | Yep, it's a straight up error in C to return the address of a local variable from a function outside of main. Valgrind will flag this as use of an uninitialized value. The problem is that as long as it's something where the calling function checks it immediately after the function exits and never looks again (something like an error code or choosing a code path based on the result) they often get away with it, especially in single threaded code. I'm running into this at this very moment as I'm trying to make my application run cleanly, but some of the libraries are chock full of this pattern. One big offender is the Unix port of Microsoft's ODBC library, at least the Postgre integration piece. I also blame the Unix standard library for almost having this pattern but not quite. Functions that return some kind of internal state that the programmer is told not to touch. Later they had to add a bunch of _r variants that were thread safe. The standard library functions don't actually have this flaw due to how they define their variables, but from the outside it looks like they do. It makes beginning programmers think that is how the functions should work and write their code in a similar manner. | | |
| ▲ | jcalvinowens 2 hours ago | parent [-] | | > Yep, it's a straight up error in C to return the address of a local variable from a function Sure, that's true, but nobody is suggesting returning the address of a local variable anywhere in this thread. I'm describing putting a pointer to a local variable in a global data structure, which is safe so long as the function doing it is somehow guaranteed not to return until the pointer is removed from the global data structure. |
|
|
|
| ▲ | rbanffy 2 hours ago | parent | prev [-] |
| I would imagine variables that are passed to functions would be considered ABI-visible. If the compiler is smart enough, it can keep the pointer wide when it’s passed to a function that’s also being compiled and act accordingly on the other side, but that worries me because this new meaning of “pointer” is propagating to parts of the code that might not necessarily agree with it. |