1

I would like to allocate a set amount of memory for the program upon initialization so that other programs cannot steal memory from it. Essentially, I would like to create a Heap for my program (without having to program a heap module all for myself).

If this is not possible, can you please refer me to a heap module that I can import into my project? Using C++17.

Edit: More specifically, I am trying to for example specify that it is only allowed to malloc 4MB of data for example. If it tries to allocate anymore, it should throw an error.

Warren Niles
  • 184
  • 9
  • 2
    You could allocate your memory in the beginning and make a custom allocator that operates on that memory. Then use that allocator for all allocations e.g. `std::vector vec;`. – Timo Aug 05 '20 at 06:40
  • 2
    https://stackoverflow.com/questions/2492934/c-reserve-memory-space – bolov Aug 05 '20 at 06:41
  • 2
    You _have_ a heap for your program. It's managed by `new`/`delete`. Unless you have some very specialized usage pattern I doubt you're going to do better than the standard library's implementation. – Miles Budnek Aug 05 '20 at 06:49
  • 1
    Your OS almost certainly overcommits memory anyway. Even allocating a huge chunk of RAM doesn't mean you'll necessarily have it when you need it. – cdhowie Aug 05 '20 at 06:50
  • @cdhowie that’s only true if the the OS uses swaping or memory compression. But if you don’t use a swap file then you indeed might need/want to reserve all memory you need before. Disabling swapping is not that uncommon for certain usecases. – t.niese Aug 05 '20 at 07:35
  • 1
    What other programs would steal from it? This sounds like an XY Problem. If you're having memory pressures issues there's better ways of dealing with it than being a difficult. Maybe the reason you're having pressure problems is because other programs employ this strategy and allocate memory they don't really need. – tadman Aug 05 '20 at 07:40
  • What is program doing, and why do you need to pre- allocate memory? – Basile Starynkevitch Aug 07 '20 at 10:27
  • @BasileStarynkevitch I am trying to make my own memory caching system and want to make sure that if I configure it to be allowed to use N bytes of memory, it is guaranteed those N bytes of memory. Furthermore, if it attempts to calloc more memory, it will fail. Essentially, a container that limits physical resources without the need to use docker or other container management systems on top of it. – Warren Niles Aug 17 '20 at 00:30

3 Answers3

2

What you ask is not possible with the features provided by ISO C++.

However, on most common platforms, reserving physical RAM is possible using platform-specific extensions. For example, Linux provides the function mlock and Microsoft Windows provides the function VirtualLock. But, in order to use these functions, you must either

  1. know which memory pages the default allocator is using for memory allocation, which can get messy and complicated, or
  2. use your own implementation of a memory allocator, so that it can itself call mlock/VirtualLock whenever it receives memory from the operating system.

Your own implementation of a memory allocator could be as simple as forwarding all memory allocation request to the operating system's kernel, for example using mmap on Linux or VirtualAlloc on Windows. However, this has the disadvantage that the granularity of all memory allocation requests is the size of a memory page, which on most systems is at least 4096 bytes. This means that even very small memory allocation requests of a few bytes will actually take 4096 bytes of memory. This would be a big waste of memory. Also, in your question, you stated that you wanted to preallocate a certain amount of memory when you start your application, so that you can use that memory later to satisfy smaller memory allocation requests. This cannot be done using the method described above.

Therefore, you may want to consider using a "proper" memory allocator implementation, which is able to satisfy several smaller allocation requests using a single memory page. See this list on Wikipedia for a list of common implementations.

That said, what you describe may be an XY problem, depending on what operating system you are using. For example, in contrast to Windows, Linux will typically overcommit memory. This means that the Linux kernel will allow applications to allocate more memory than is actually available, on the assumption that most applications will not use all the memory they request. Therefore, a call to std::malloc or new will seldom fail on Linux (but it is still possible, depending on the configuration). Instead, under low memory conditions, the Linux OOM killer (out of memory killer) will start killing processes that are taking up large amounts of memory, in order to free up memory and to keep the system running.

For this reason, the methods described above are likely to work on Microsoft Windows, but on Linux, they could be counterproductive, as they would make your process more likely to fall prey to the OOM killer.

However, even if you are able to accomplish what you want using the methods described above, I generally don't recommend that you use these methods, as this behavior is unfair towards the other processes in the system. Generally, you should leave the task of deciding which process gets (fast) physical memory and which process gets (slow) swap space to the operating system, as the operating system can do a better job of fairly distributing its resources among its processes.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
1

If you want to force actual allocation of memory pages to your process, there's no way around managing your own memory.


In C++, the canonical way to do this would be to write an implementation for operator new() and operator delete() (the global ones!) which are responsible to perform the actual memory allocation. The function signatures are:

void* operator new (size_t size);
void operator delete (void *pointer);

and you'll need to include the #include <new> header.

Your implementation can do its work via one of three possible routes:

  • It allocates the memory using the C function malloc(), and immediately touches each memory page by writing a value to it. This forces the system kernel to actually back the memory region with real memory.

  • It allocates the memory using malloc(), and proceeds to call mlockall(). This is the nuclear option for when you absolutely must avoid all paging, including paging of code segments and shared libraries.

  • It asks the kernel directly for some chunks of memory using mmap() and proceeds to lock them into RAM via mlock(). The effect is similar to the previous option, but it is targeted only at the memory you allocated for your operator new() implementation.

The first method works independent of the OS kernel, the other two assume a Linux kernel.


With GCC, you can perform the memory allocation before main() is called by using the __attribute__((constructor)).


Writing such a memory allocator is not rocket science. It's not even a lot of code if done right. I once wrote an operator new()/operator delete() implementation that fits into 170 lines, including all my special features, comments, empty lines, and the license declaration. It's really not that hard.

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
0

I would like to allocate a set amount of memory for the program upon initialization so that other programs cannot steal memory from it.

Why would you want to do that?

it is not your business to decide if your program is more important than others !

Imagine your program running in parallel with some printing utility driving the printer. This is a common occurrence: I have downloaded some long PDF document (e.g. several hundred pages, like the C++ standard n3337), and I want to print it on paper to study it in a train, an airplane, at home and annotate it with a pencil and paper. The printing is likely to last more than an hour, and require computing resources (e.g. on Linux some CUPS printer driver converting PDF to PCL). During the printing, I could use your program.

If I am a user of your program, you have decided (at my place) that printing that document is less important for me than using your program (while the printer is slowly spitting pages).

Leave the allocation and management of memory to the operating system of your user.

There are of course important exceptions to that common sense rule. A typical medical robot used in neurosurgery has some embedded software with constraints different of a web server software. See also this draft report. For Linux, read Advanced Linux Programming then syscalls(2).

More specifically, I am trying to for example specify that it is only allowed to malloc 4MB of data for example.

This is really simple. Some OSes provide the ability to limit resources (on Linux, see setrlimit(2)...). Write your own malloc routine, above operating system specific primitives such as (on Linux) mmap(2). See also this, this and that answers (all focused on Linux; adapt them to your particular operating system). You probably can find open source implementations of malloc (on github or gitlab) for your particular operating system. For Linux, look here, then study the source code of glibc or musl-libc. In C++, study the source code of GCC or Clang (probably ::operator new is using malloc)

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547