Sujet : Re: Memory protection between compilation units?
De : david.brown (at) *nospam* hesbynett.no (David Brown)
Groupes : comp.lang.cDate : 11. Jun 2025, 16:14:44
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <102c6h4$21qct$1@dont-email.me>
References : 1
User-Agent : Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.11.0
On 11/06/2025 15:32, Mateusz Viste wrote:
This might not be a strictly C question, but it definitely concerns all
C programmers.
Earlier today, I fixed an out-of-bounds write bug. An obvious issue:
static int *socks[0xffff];
void update_my_socks(int *sock, int val) {
socks[val & 0xffff] = sock;
}
While the presented issue is common knowledge for anyone familiar with
C, *locating* the bug was challenging. The program did not crash at the
moment of the out-of-bounds write but much later - somewhere entirely
different, in a different object file that maintained a static pointer
for tracking a position in a linked list. To my surprise, the pointer
was randomly reset to NULL about once a week, causing a segfault.
Tracing this back to an unrelated out-of-bounds write elsewhere in the
code was tedious, to say the least.
This raises a question: how can such corruptions be detected sooner?
Protected mode prevents interference between programs but doesn’t
safeguard a program from corrupting itself. Is there a way to enforce
memory protection between module files of the same program? After all,
static objects shouldn't be accessible outside their compilation unit.
How would you approach this?
Your key tools for catching such errors early are static error checking and then run-time checkers. Then when you get strange symptoms, a debugger.
Static error checking (like gcc -O2 -Wall -Wextra) will not catch everything, but it will catch /some/ out-of-bounds errors and other bugs. The more you catch there with your compiler, the better. There are also more advance static error checking tools for special situations, or special prices.
Run-time checks like valgrind or gcc / clang sanitizers can catch quite a lot of out-of-bounds accesses and other run-time errors. They can take some practice to use well, and can have a significant impact on the run-time characteristics of the code (such as timing or memory usage) which may then affect the way the code is run. And of course they won't catch bugs unless the buggy parts of the code are actually run in a way that triggers the problem.
For debugging problems like this with gdb, you can put a data breakpoint on the pointer that is your known symptom. Set it to stop when something writes 0 to it - then you can see where you are in code when that happens. Of course, that will be a real pain if it only happens once a week.
If you suspect a buffer overflow, then you can also look in your map file for the pointer, and then look at what is next to it in memory. This is inconvenient with static data - you have to combine it with listing files, as the details of static data don't make it through to the linker-generated map files. You might see more information using a debugger.
As you can see, there is no simple solution to this!