Sujet : Re: Memory protection between compilation units?
De : lew.pitcher (at) *nospam* digitalfreehold.ca (Lew Pitcher)
Groupes : comp.lang.cDate : 11. Jun 2025, 15:30:30
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <102c3u6$206tl$1@dont-email.me>
References : 1
User-Agent : Pan/0.139 (Sexual Chocolate; GIT bf56508 git://git.gnome.org/pan2)
On Wed, 11 Jun 2025 15:32:39 +0200, 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.
Your questions, below, are all quite valid, and (AFAICT) all relate to
how your operating environment (OS, linker, libraries, etc) works.
In general, you prevent or detect such issues by understanding
1) the environment in which your code runs,
2) the operation and implications of each component linked into your
process, and
3) the operation and implications of each compilation unit compiled
in each component of your process.
You will not be able to completely understand some components, as
you will probably, at best, only have documentation, and not source code
for them. Others will be too complex to properly understand.
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.
For components for which you have source code, bench-checking, peer
review, unit-testing, integration testing, compliance testing, and
performance testing should catch most flaws. Use the appropriate
tools: a language linter to catch language usage errors, a profiling
program to find where your code spends it's time, and a memory-use
tracking program (like valgrind, for instance) to catch out-of-bounds
conditions.
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.
This all depends on your linker/binder and your operating environment
(OS, etc). The linker or binder arranges your compilation units into
a cohesive whole, combining and arranging static memory areas, code
blocks, etc, to suit the requirements of you operating environment.
Your operating environment arranges all that into memory in order
to execute the code, which means moving those static memory blocks,
dynamic blocks, and code blocks around. The end result is that,
when executing, the placement and boundaries of each compilation-unit's
"static" memory depends entirely on where the linker and OS decide
they should be. Objects that live "in isolation" in the source code
may occupy contiguous sequential memory locations in execution. The
OS may or may not provide some sort of "fencing" around objects or
blocks.
How would you approach this?
Carefully. Very carefully.
I could tell stories..... :-)
HTH
-- Lew Pitcher"In Skills We Trust"