I'm working on legacy code that uses mmap to load data from a file:
int fd;
std::size_t fs;
fd = open(filename, O_RDONLY); // error management omitted for the example
fs = get_size_from_fd(fd); // legacy function using fstat
void *buff = mmap(NULL,fs,PROT_READ,MAP_SHARED,fd,0);
(NB: large parts are still using a C API, but I'm compiling in C++ and trying to update as much as possible, fixing issues and UB first).
Later in the code, I'm finding:
unsigned char *ptr = (unsigned char*)buff; // legacy code, first change would be to make it a reinterpret_cast
// then loops on bytes from ptr.
AFAIK, there is no implicit array of bytes at buff (see https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p1839r7.html) so, instead I want to emulate start_lifetime_as:
unsigned char *get_object_representation(void *buffer, std::size_t N)
{
std::memmove(buffer, buffer, N); // implicitly creates an array of unsigned char
return std::launder(reinterpret_cast<unsigned char *>(buffer));
}
And then I could do:
unsigned char *ptr = get_object_representation(buff,fs);
// then loops on bytes from ptr
This requires C++20 for implicit lifetime creation, I believe.
But, is it correct? I've got myself an objection with the use of std::memmove because it requires that an object of size at least N exists at buffer. Yet I don't think that mmap formalizes such a guarantee.
https://man7.org/linux/man-pages/man2/mmap.2.html says only:
On success, mmap() returns a pointer to the mapped area
Otherwise, is there a proper way to access bytes accessible from mmap in a well-defined way (possibly in older C++ also)?
static_casthere rather than areinterpret_cast. Shouldn't make a difference in functionality. Thestatic_castis just narrower in what it can do.std::memmove(buffer, buffer, N)whenbufferis mapped read-only? If thememmoveisn't optimized out, then this will segfault.