4 ms·
The first comment there (by Anonymous) claims that the final technique can also be optimized: (memset_ptr)(p, 0, len); > can be replaced by: if (mems
by BrandonM 12y ago
The first comment there (by Anonymous) claims that the final technique can also be optimized:
(memset_ptr)(p, 0, len);
> can be replaced by:
if (memset_ptr == memset) {
memset(p, 0, len);
} else {
memset_ptr(p, 0, len);
}
> Which in turn can be optimized using the other tricks noticed above into:
if (memset_ptr != memset) {
memset_ptr(p, 0, len);
}
I'm no expert, but this seems like a believable defeat of the technique in the post.
- cperciva 12y agoThat's not quite right since it's now reading memset_ptr twice, but the concept does seem to be right -- the volatile pointer must be read but the standard doesn't require that the function is invoked.
- kelnos 12y agoHow about instead of assigning to your function pointer directly using `memset`, instead use `dlsym()` to look it up? You could even declare the fnptr to take a `volatile` argument as well as the ptr itself being `volatile` (not sure that is useful here). Of course, using `dlsym()` isn't exactly portable...
- spott 12y agoWhat about a data race? Theoretically, the function that memset_ptr points to could be changed between when it is checked and when it would be run.
- Karellen 12y agoIf you have multiple threads accessing a shared (mutable) variable in your program, even a shared volatile variable, then you need to guard every access to that variable (which, in this case, includes every function call through memset_ptr) with proper thread synchronisation primitives. Marking a variable "volatile" is not enough to prevent data races in a multi-threaded environment. If you've put a semaphore, or mutex lock, or whatever around your calls through memset_ptr(), the transformations will all take place inside the lock, and data races should not be an issue.
- spott 12y agoI think you missed my point. memset_ptr is a const (not changed by this program... theoretically) volatile (allowed to be changed by the system, theoretically) pointer to memset. In THIS PARTICULAR CASE, memset_ptr points to memset. The compiler however doesn't know that it won't change due to another processes, but we do. So the compiler shouldn't be able to optimize out the call directly to the function pointer because it introduces a possible race condition: the program reads that memset_ptr points to memset, then the pointer changes (due to some other process changing it), but the program still calls memset, and not memset_ptr. The optimization allows for a possible race condition to occur.
- tedunangst 12y agoThat race exists regardless. Many systems will execute this as loading the pointer into a register, them jumping to it. The value could change between those two instructions.