@jasnell said
Alternatively, it may be a bit cleaner to use a custom smart pointer with a deleter for these...
e.g. bit more verbose...
struct Mmap { void* mem = nullptr; size_t size = 0; Mmap(void* start, size_t size, int prot, int flags) { mem = mmap(start, size, prot, flags, -1, 0); } }; struct MmapDeleter { void operator()(Mmap* ptr) const noexcept { if (ptr.mem != nullptr && ptr.mem != MAP_FAILED && munmap(ptr.mem, ptr.size) == -1) PrintSystemError(errno); } }; using MmapPointer = std::unique_ptr<Mmap, MmapDeleter>;then...
MmapPointer nmem; MmapPointer tmem; // ... size_t size = r.to - r.from; // ... nmem = std::make_unique(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS); if (nmem.mem == MAP_FAILED) goto fail; // ... tmem = std::make_unique(start, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED); if (tmem.mem == MAP_FAILED) goto fail;
@jasnell @addaleax IINM it would introduce an additional level of indirection to go with std::unique_ptr, because the structure Mmap would have to be heap-allocated and then the void* would be stored within that.
AFAICT std::unique_ptr is good for pointer types that can be freed with FreeThisPointerType(PointerType* ptr); If an additional argument needs to be given to the deleter then that argument, along with the pointer, must be stored in a structure, which becomes heap-allocated if we use std::unique_ptr.
@gabrielschulhof Right, I think this is sometime the Mmap (or let鈥檚 be verbose and call it MemoryMapping) class can take of itself in its constructor/destructor. std::unique_ptr or friends don鈥檛 really seem to make sense here to me either.
That's what I was thinking too. A simple class which, in its constructor performs mmap(2) and its destructor performs munmap(2).
That works for me