4

I have a c++ program running on a Windows 7 machine with 12GB memory. The compiler and linker is Visual Studio 2013 Express.

the program uses a library OGDF. I compiled the library source codes into a static library with Release X64 configuration and referenced the library in my project.

when I run the problem (Debug x64 configuration) , a exception are thrown from the code in the OGDF library indicating that no enough memory available;

    E *p = static_cast<E *>( realloc(m_pStart, sNew*sizeof(E)) );
    if(p == 0) OGDF_THROW(InsufficientMemoryException);

I paused the program and opened the debug window and checked the value of sNew = 9M and sizeof(E) = 8, so it was allocating 72M memory and failed.

At the debug time I opened windows task manager, it shows that my program's memory usage (working set size and commited size) is less than 2MB

So I am very confused why the REALLOC will fail since there are enough memory available (>4GB)? even if there are lots of fragments in my heap, the committed size is less than 2MB so there should be enough memory.

For test propose I inserted the following code before my call to the library function:

void* ddd = malloc(1200000000);
char* b = (char*)ddd;
char ttt = 3;
int g = 0;
for (g = 0; g < 1200000000;++g)
{
    *(b + g) = ttt;
}
ddd=realloc(ddd, 2400000000);
b = (char*)ddd;
for (g = 0; g < 2400000000; ++g)
{
    *(b + g) = ttt;
}

the code above runs OK (Debug x64 configuration) and the task manager shows my memory usage (working set and committed size) is about 2.3GB before I called free() . So in my program I can allocate more than 2GB memory on my heap, why does the 72MB alloc in the library code fail ?

EDIT:

I found the problem.

The debugger showed me WRONG local variable data when I am using release-configuration compiled library file. The actual cause is the library is calling realloc(ptr,0).

user2218067
  • 155
  • 2
  • 13
  • 1
    How large is your paging file? – David Schwartz Nov 25 '15 at 09:40
  • Why are you using realoc in a C++ program? Do you have a legacy library to interface with? – n. m. could be an AI Nov 25 '15 at 10:03
  • 2
    Are you possibly mixing heaps? Namely, if your buffer is allocated by a debug heap and the library is compiled for release, each module will use a different heap. Then, the library will probably not be able to reallocate a buffer allocated on a heap it's not managing. – Eran Nov 25 '15 at 10:33
  • @David Schwartz the paging file size is windows default size, I didn't remember the number, maybe I can check it tomorrow. But since I can successfully use and free 2.4GB memory before the call to the library function, Can I say that there are enough "memory" (RAM+pagefile and VA space) for the OS to commit ? – user2218067 Nov 25 '15 at 17:36
  • @eran I complied the library into static object file (not dll) and used the library in my project. So the `realloc` in my project and `realloc` in the compiled library are using different heaps and they have different size limitations? If that's true do you know how to make them to use a same heap? I checked the MSDN and there is an option of linker about heap size [link](https://msdn.microsoft.com/en-us/library/f90ybzkh.aspx), it said "default heap size is 1MB" and this also confused me because I can alloc GBs of memory without changing my linker option but the library code can use <2MB only – user2218067 Nov 25 '15 at 17:52
  • @user2218067 No, you can't say that. You have free *RAM*, but you are trying to allocate backed memory. A system can have lots of free RAM but no available backed memory because of prior reservations. See my answer. (But it's starting to seem likely that your real issue is what eran is talking about.) – David Schwartz Nov 25 '15 at 19:04
  • @user2218067, MS CRT (C runtime) has two types of heaps - debug and release, used by matching build configurations. When building your executable using the debug configuration, you have to make sure all modules (libs - static libraries and dlls - dynamic libraries) were built using the same configuration. Take a look at how the OGDF library was built, and make sure you use the same configuration (most importantly, the `_DEBUG` definition) for your code. – Eran Nov 25 '15 at 20:26
  • @eran After I recompiled the library in debug configuration I found that debugger is showing WRONG value of local variables in the library code when using release-version library. By using debug library the local variable value is corrent and I found the actual problem is that the library have a bug ,it passes size 0 to realloc(). Thank you for mentioning the mixed heap problem :) – user2218067 Nov 26 '15 at 08:24
  • I doubt the debugger is showing the wrong value due to an internal bug. It's more likely that there's some discrepancy between the lib, the debug symbols (pdb file) or the source. Alternatively, local variables might be optimized out and the code slightly reordered, so you don't see what you expect. Whether the library itself has a bug I don't know, but I'm glad your problem is solved. – Eran Nov 26 '15 at 08:33

1 Answers1

2

Your question is very similar to "Why won't you write me a check for $500? You have $2,000 in the bank."

Operating systems get requests for memory before that memory is used. An operating system can't grant a memory allocation request unless it has enough backing store for all the requests it has already permitted, whether or not they are currently using any RAM.

For example, if you malloc 1GB but haven't accessed the allocated virtual address space yet, much less than 1GB of RAM will be used by that allocation. But until that allocation is released, the system must reserve 1GB of backing store (RAM or swap) just in case your program starts using that allocated space.

If the system has too many such allocations, even if it has plenty of free RAM, it will refuse new allocations. Windows won't overcommit because that risks having to forcibly terminate applications should those mappings later require more backing store than the OS has.

A good way to avoid these misunderstandings in the future is to avoid using the word "memory" by itself. If you mean RAM, say "RAM" or "physical memory". If you mean backing store, say "backing store". If you mean address space, say "virtual memory".

You say things like, "I have lots of free memory, so I should be able to allocate memory." That sounds like a mystery. But if you had more accurately said, "I have lots of free RAM, why can't I allocate more virtual memory (or backed memory)?", you would be halfway to the answer.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • My Win8 says the minimal size of page file is 16MB. If your statement is true, this legal setting wouldn't have allowed the system to load. Given the numbers he provides (64 bit, 12GB RAM, allocation of 72MB), I doubt the page file is the reason. – Eran Nov 25 '15 at 09:53
  • @eran Huh? I cannot make any sense of your comment whatsoever. It literally seems like word salad. (That a 72MB allocation failed just means that the OS has less than 72MB of unreserved backing store left.) – David Schwartz Nov 25 '15 at 09:54
  • I assume that by "Backup store" you refer to the page file. The page file can be very small, regardless of the size of the RAM (not recommended, but legal). If every allocated byte must have a matching storage in the page file, setting the page file to 16MB would have allowed only 16MB of memory to be allocated. Bon appetit. – Eran Nov 25 '15 at 10:00
  • Backing store refers to the page file when you're talking about RAM. But I'm talking about an allocation of virtual memory, not RAM. Those can be backed by either RAM or page file, so long as the space is not reserved by a prior allocation (whether or not that allocation is using it). – David Schwartz Nov 25 '15 at 10:03
  • He's compiling to 64 bit, so there's no shortage in virtual address space for sure (unless the requested allocation size is not as said). If you're referring to the case in which total memory consumption nears page file + RAM size - the OP says he has >4GB of memory available; if that's true, he should be far from the backup store limit. – Eran Nov 25 '15 at 10:22
  • I'm not talking about virtual address space. Yes, he has plenty of virtual address space and plenty of free RAM. What he doesn't have is unreserved backing store (RAM or swap) to back the allocation (because it's been reserved by previous allocations that aren't using RAM yet). When you call `realloc` to grow an allocation, that allocation will fail if there is insufficient backing store to back that allocation and every previous allocation the OS has allowed, regardless of how much RAM those allocations are using. Please read my answer again. – David Schwartz Nov 25 '15 at 10:37