I recently wrote about exploring
munmap()
on page zero , and in the process looked at the POSIX specification for
munmap()
. One of my discoveries about the practical behavior of Unixes here is that OpenBSD specifically disallows using
munmap()
on address space that isn't currently mapped (see
munmap(2)
). In my entry, I said that it wasn't clear whether POSIX strictly authorized this behavior, although you could put forward an interpretation where it was okay.
In a comment, Jakob Kaivo put forward the view that POSIX permitted this and any other behavior for when
munmap()
was applied to unmapped address space because of a sentence in the end of the Description :
The behavior of this function is unspecified if the mapping was not established by a call to
mmap().
At first reading this seems clear. But wait, it's time to get confused. Earlier in the same description of
munmap()
's behavior, POSIX clearly says that it can be used if there is no mapping:
[...] If there are no mappings in the specified address range, then
munmap()has no effect.
(Note that 'has no effect' is different from 'unspecified'.)
POSIX doesn't require that this not raise an error, but you can read its description of when you can get
EINVAL
to require that you don't (some of the time). Assuming
addr
is aligned and
len
is not zero, you get EINVAL if some of the address space you're unmapping is 'outside the valid range for the address space of a process', and perhaps implicitly not otherwise. And then you have the question of what POSIX intended here by saying 'a process space' instead of 'the (current) process'.
One of the things we can see here is that it's hard for non-specialists to truly read and understand the POSIX standards . Both Jakob Kaivo and I are at least reasonably competent C and Unix programmers and we've both attempted to read a reasonably straightforward POSIX specification of a single function, yet we've wound up somewhere between disagreeing and being uncertain about what it allows.
This is a useful lesson for me to remember any time I'm tempted to appeal to a POSIX standard for how something should work. POSIX standards are written in specifications language, and if they're not completely clear I should be cautious about how correct I am. Probably I should be cautious even if they seem perfectly clear.
(And anyway, the actual behavior of current Unixes matters more than what POSIX says. A POSIX specification is merely a potential lower bound on behavior, especially future behavior. If a Unix does something today and that something is required by POSIX, the odds are good that it will keep doing that in the future.)
PS: My interpretation of the unspecified behavior versus 'no behavior' here is that POSIX is saying that it's unspecified what happens if you
munmap()
legitimate address space that wasn't obtained through your own
mmap()
. For instance, if you
munmap()
part of something that you got with
malloc()
, anything goes as far as POSIX is concerned. It might work and not produce future problems, it might have no effect, it might kill your program immediately, and it might cause your program to malfunction or blow up in the future.