Reputation: 1705
Here is the scenario: I am declaring an array and NOT USING IT ANY WHERE IN THE PROGRAM yet. If I declare it to be of length 100 or less, it works fine. For greater length, it gives segmentation fault. I can't understand this behavior.
ATL_RAM_BUFFER_L3 an_unknown_array[128];
Where ATL_RAM_BUFFER_L3 is a structure of almost 72KB.
Upvotes: 3
Views: 3191
Reputation: 881153
You're blowing out your stack which is typically a limited resource, in your case not enough to hold the nine or so megabytes your array takes up.
There are a couple of possible solutions. If you only need one copy, you can declare it outside the function (or as a static within the function) - this will generally keep it off the stack and put it into an area with less limited storage.
Alternatively, you can allocate it dynamically, and ensure you manage it properly.
You may also be able to configure a larger stack size depending on the environment.
By way of example, the following bash
script will work out how much data you can allocate on the stack in your (default) environment:
((sz = 0))
((delta = 1000000))
while [[ ${delta} -gt 0 ]]; do
while true; do
sleep 1
((sz += delta))
printf "Trying ${sz} ... "
rm -f qq.c
echo "#include <stdio.h>" >>qq.c
echo "int main (void) {" >>qq.c
echo " char buff[${sz}];" >>qq.c
echo " puts (\"hello\");" >>qq.c
echo " return 0;" >>qq.c
echo "}" >>qq.c
gcc -o qq qq.c
trap 'echo "segfault!"' CHLD
rm -f flagfile
( bash -c './qq >flagfile 2>/dev/null' ) >/dev/null 2>&1
if [[ "$(cat flagfile)" == "hello" ]]; then
echo "okay"
else
echo "crashed"
((sz -= delta))
break
fi
done
((delta = delta / 10))
done
It works by constructing a C program of the form:
#include <stdio.h>
int main (void) {
char buff[XYZZY];
puts ("hello");
return 0;
}
where XYZZY
is gradually changed to see where the program first crashes from lack of stack space. The output in my environment (CygWin) goes something like this:
Trying 1000000 ... okay
Trying 2000000 ... okay
Trying 3000000 ... crashed
Trying 2100000 ... crashed
Trying 2010000 ... okay
Trying 2020000 ... okay
Trying 2030000 ... okay
Trying 2040000 ... okay
Trying 2050000 ... okay
Trying 2060000 ... okay
Trying 2070000 ... okay
Trying 2080000 ... crashed
Trying 2071000 ... crashed
Trying 2070100 ... crashed
Trying 2070010 ... okay
Trying 2070020 ... okay
Trying 2070030 ... okay
Trying 2070040 ... okay
Trying 2070050 ... okay
Trying 2070060 ... okay
Trying 2070070 ... crashed
Trying 2070061 ... okay
Trying 2070062 ... okay
Trying 2070063 ... okay
Trying 2070064 ... okay
Trying 2070065 ... crashed
meaning that two megabytes is about where it maxes out.
Upvotes: 4
Reputation: 13672
The memory for local variables is assigned/freed on the run time. They get created on stack and every thread/process has a limited stack. The size of the stack largely depends on the compiler and operating system. It varies from one system to another. In Unix/Linux type of systems, programs will through segmentation fault when stack overflow occurs. Look at this document for more details on this subject.
On the other hand, the memory for global variables get allocated when the program is loaded in memory. They are assigned memory in BSS section if they were not initialized or Data section if they were initialized to some value. Normally these sections have a lot more room than the stack of a process. So it is generally advisable to declare large variables/objects, like yours, globally to avoid this problem.
Upvotes: 0