I am just about finished reading K&R, and that is all the C that I know. All my compilation is done from Windows command line using MinGW, and I have no knowledge of ad
You're running into a stack overflow.
Local automatic storage variables (such as megabyte
) are allocated on the stack, which has limited amount of space. malloc allocates on the heap, which allows much larger allocations.
You can read more here:
http://en.wikipedia.org/wiki/Stack_overflow
(I should note that the C language does not specify where memory is allocated - stack and heap are implementation details)
The size of the stack in a Windows program is usually around 1 MB, so on the second recursion, you're overflowing the stack. You shouldn't be allocating such large arrays on the stack, use malloc
and free
to allocate and deallocate the memory on the heap (there's no way to get around malloc
for such sizes of arrays):
void alloc_one_meg() {
int *megabyte = malloc(sizeof(int) * 250000); // allocate space for 250000
// ints on the heap
int i;
for (i=0; i<250000; i++) {
megabyte[i] = rand();
}
j++;
printf("Loop %d\n", j); // ghetto debug
if (j<1000) {
alloc_one_meg();
}
free(megabyte); // DO NOT FORGET THIS
}
That said, you can actually change the stack size of a program and make it bigger (though I'd only do so as an educational exercise, not in production code). For Visual Studio you can use the /F compiler option, and on linux you can use setrlimit(3). I'm not sure what to use with MinGW though.
StackOverflow. Is this a trick question?
The memory you are allocating via the recursive functional calls is allocated from the stack. All of the stack memory must be contiguous. When your process starts a thread, Windows will reserve a range of virtual memory address space for that thread's stack. The amount of memory to be reserved is specified in your EXE file's "PE header." PE stands for "Portable Executable."
Using the dumpbin
utility included with Visual Studio, with itself (dumpbin.exe
) as the input file:
dumpbin /headers dumpbin.exe
... there is some output, and then:
100000 size of stack reserve
2000 size of stack commit
The "100000" is a hexadecimal number equal to 1,048,576, so this represents around 1MB.
In other words, the operating system will only reserve a 1MB address range for the stack. When that address range is used up, Windows may or may not be able to allocate further consecutive memory ranges to increase the stack. The result depends on whether further contiguous address range is available. It is very unlikely to be available, due to the other allocations Windows made when the thread began.
To allocate a maximum amount of virtual memory under Windows, use the VirtualAlloc
family of functions.