13

This is in C++ on CentOS 64bit using G++ 4.1.2.

We're writing a test application to load up the memory usage on a system by n Gigabytes. The idea being that the overall system load gets monitored through SNMP etc. So this is just a way of exercising the monitoring.

What we've seen however is that simply doing:

char* p = new char[1000000000];

doesn't affect the memory used as shown in either top or free -m

The memory allocation only seems to become "real" once the memory is written to:

memcpy(p, 'a', 1000000000);   //shows an increase in mem usage of 1GB

But we have to write to all of the memory, simply writing to the first element does not show an increase in the used memory:

p[0] = 'a';    //does not show an increase of 1GB.

Is this normal, has the memory actually been allocated fully? I'm not sure if it's the tools we are using (top and free -m) that are displaying incorrect values or whether there is something clever going on in the compiler or in the runtime and/or kernel.

This behavior is seen even in a debug build with optimizations turned off.

It was my understanding that a new[] allocated the memory immediately. Does the C++ runtime delay this actual allocation until later on when it is accessed. In that case can an out of memory exception be deferred until well after the actual allocation of the memory until the memory is accessed?

As it is it is not a problem for us, but it would be nice to know why this is occurring the way it is!

Cheers!

Edit:

I don't want to know about how we should be using Vectors, this isn't OO / C++ / the current way of doing things etc etc. I just want to know why this is happening the way it is, rather than have suggestions for alternative ways of trying it.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
fwg
  • 1,018
  • 2
  • 10
  • 25

3 Answers3

17

When your library allocates memory from the OS, the OS will just reserve an address range in the process's virtual address space. There's no reason for the OS to actually provide this memory until you use it - as you demonstrated.

If you look at e.g. /proc/self/maps you'll see the address range. If you look at top's memory use you won't see it - you're not using it yet.

Erik
  • 88,732
  • 13
  • 198
  • 189
  • I've had some experience on this and i think the memory association and garbage collection methods in modern compilers also affect the issue. Do you have technical info on this? – Hossein Mar 17 '11 at 15:51
  • There's no garbage collection in c++ - it's not related. In java or C# that could in theory be an additional cause though. For details, start with wikipedia's page on *Virtual address space* – Erik Mar 17 '11 at 15:55
  • I think it's a common feature of Unix. It could potentially cause hell, since the system makes your application believe it will be able to satisfy its requests but may then not be in a position too, however in practice I suppose it yields a lower memory consumption. – Matthieu M. Mar 17 '11 at 16:01
  • 1
    @Matthieu: It is specific to Linux (overcommit) and even there it can be disabled. – Nemanja Trifunovic Mar 17 '11 at 16:11
  • @Nemanja: can you disable it on a per-process basis, or is it for the whole system at once ? – Matthieu M. Mar 17 '11 at 16:18
  • @Matthieu: AFAIK it is per system, not per process, but check the documentation: http://linux-mm.org/OverCommitAccounting – Nemanja Trifunovic Mar 17 '11 at 16:33
8

Please look up for overcommit. Linux by default doesn't reserve memory until it is accessed. And if you end up by needing more memory than available, you don't get an error but a random process is killed. You can control this behavior with /proc/sys/vm/*.

IMO, overcommit should be a per process setting, not a global one. And the default should be no overcommit.

AProgrammer
  • 51,233
  • 8
  • 91
  • 143
2

About the second half of your question:

The language standard doesn't allow any delays in throwing a bad_alloc. That must happen as an alternative to new[] returning a pointer. It cannot happen later!

Some OSs might try to overcommit memory allocations, and fail later. That is not conforming to the C++ language standard.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203