Re:My Most Important C++ Aha Moments (2006)
by SamReidHughes on Monday June 27, 2016 @04:36PM
(#11989273)
> Copy construction out of a global is actually still unsafe, because some other thread (for example) might mutate the global, invalidating the this pointer.
It's not unsafe, that code wouldn't pass the check. Other threads would have to not access globals at all, or all threads have to access them read-only.
As for doing things on a variable by variable basis, just imagine a rote refactoring from a global variable to non-global variable passed up from main. For example:
We eliminate the global variable "as" by passing a struct assoc pointer parameter up from main.
The parts of this that isn't a rote refactoring is where, instead of adding another parameter to functions like event_handler and event_set, modifying libevent to pass through the struct assoc pointer, we instead put the struct assoc pointer into a closure (because this is C, whatever homespun kludge is most convenient). The other situation where it's put into a closure is some calls to pthread_create.
We know that this refactoring retains identical behavior -- every access to the global as now accesses the same as object -- because only one instance of struct assoc has been constructed. (And the kludges with C-style closures here are correct merely by inspection, i.e. the right variables are initialized, type safety would handle that.)
Now, if we have some tool for checking use of globals, it can do the same thing, and then analyze memory safety using the rules it uses for non-globals. What it needs from the user are annotations to help it know when and how a global reference should be captured by a closure instead of passed as an extra parameter to the closure. Of course, it would be perfectly valid to thread a struct assoc pointer parameter through the internals of libevent, if that was sufficient to check the program.
Now, memcached would have other problems to deal with, because the struct assoc is shared across threads. The point is, the problem is not that it's a global variable, it's other structure inherent to how the program is designed. And examples like
It's not unsafe, that code wouldn't pass the check. Other threads would have to not access globals at all, or all threads have to access them read-only.
As for doing things on a variable by variable basis, just imagine a rote refactoring from a global variable to non-global variable passed up from main. For example:
https://github.com/srh/memcached/compare/65da75f...235db6
We eliminate the global variable "as" by passing a struct assoc pointer parameter up from main.
The parts of this that isn't a rote refactoring is where, instead of adding another parameter to functions like event_handler and event_set, modifying libevent to pass through the struct assoc pointer, we instead put the struct assoc pointer into a closure (because this is C, whatever homespun kludge is most convenient). The other situation where it's put into a closure is some calls to pthread_create.
We know that this refactoring retains identical behavior -- every access to the global as now accesses the same as object -- because only one instance of struct assoc has been constructed. (And the kludges with C-style closures here are correct merely by inspection, i.e. the right variables are initialized, type safety would handle that.)
Now, if we have some tool for checking use of globals, it can do the same thing, and then analyze memory safety using the rules it uses for non-globals. What it needs from the user are annotations to help it know when and how a global reference should be captured by a closure instead of passed as an extra parameter to the closure. Of course, it would be perfectly valid to thread a struct assoc pointer parameter through the internals of libevent, if that was sufficient to check the program.
Now, memcached would have other problems to deal with, because the struct assoc is shared across threads. The point is, the problem is not that it's a global variable, it's other structure inherent to how the program is designed. And examples like
are easily dealt with.