Stack full detection

When writing code in C ++, I found out that using a stack to store memory is a good idea.

But lately, I have run into a problem:

I had an experiment with code that looked like this:

void fun(const unsigned int N) { float data_1[N*N]; float data_2[N*N]; /* Do magic */ } 

In this case, the code was accidentally detected with a sectioning error, and I had no idea why.

It turned out that the problem was that I was trying to store things that were large on my stack, is there any way to detect this? Or at least discover that it went wrong?

+6
source share
5 answers
 float data_1[N*N]; float data_2[N*N]; 

These are variable length arrays (VLAs) because N not a constant expression. The constant in the parameter ensures that N is read-only. It does not tell the compiler that N is a constant expression.

VLAs are allowed only on the C99; in another version of C and in all versions of C ++ they are not allowed. However, some compilers provide VLAs as a compiler extension function. If you are compiling GCC, try using the -pedantic , it will tell you that it is not allowed.

Now, why does your program give segfault, possibly due to a stack overflow due to the large N * N value:


Consider using std::vector as:

 #include <vector> void fun(const unsigned int N) { std::vector<float> data_1(N*N); std::vector<float> data_2(N*N); //your code } 
+5
source

It is extremely difficult to detect that the stack is full, but not carried at all. One of the biggest problems is that the stack frames are variable in size (especially when using variable-length arrays, which are actually just a standard way to do what you did before using alloca() ), so you cannot use simple proxies as the number of stack frames.

One of the simplest methods that are mostly portable is to place a variable (possibly of type char so that the pointer to it is char* ) at a known depth in the stack and then measure the distance from which point to a variable (of the same type) in the current stack stack using simple pointer arithmetic. Add to the estimate of how much space you are going to allocate, and you have a good guess that the stack is about to explode on you. The problems with this are that you don’t know the direction of the stack growth (no, they do not all grow in the same direction!) And developing the size of the stack space itself is pretty messy (you can try things like system restrictions, but they really quite uncomfortable). Plus, the hacking factor is very high.

Another trick I saw used only for 32-bit Windows was trying to alloca() enough space and handle a system exception that could have occurred if there was not enough space.

 int have_enough_stack_space(void) { int enough_space = 0; __try { /* Yes, that got a double-underscore. */ alloca(SOME_VALUE_THAT_MEANS_ENOUGH_SPACE); enough_space = 1; } __except (EXCEPTION_EXECUTE_HANDLER) {} return enough_space; } 

This code is very portable (for example, it doesn’t expect that it works on 64-bit Windows), and to build with the older gcc some nasty built-in assembler is required! Structured Exclusion Management (this usage) is one of the blackest black arts in Windows. (And do not return from within the __try construct.)

+2
source

Try using features like malloc instead. It will explicitly return null if it could not find a memory block with the requested size.

Of course, in this case, do not forget to free this memory at the end of the function, after you finish.

In addition, you can check the settings of your compiler, with which memory limit in the stack it generates binary files.

+1
source

One of the reasons people say that it is better to use the stack instead of heap memory may be due to the fact that variables placed on top of the stack will be automatically output when you leave the function body. To store large blocks of information, heap memory and other data structures, such as linked lists or trees, are usually used. Also, the memory allocated on the stack is limited and much less than you can allocate on the heap. I think it’s better to manage the memory allocation and release it more accurately, instead of trying to use the stack to store big data.

You can use a framework that manages your memory allocations. In addition, you can use VDL to check for memory leaks and memories that have not been released.

+1
source

Is there any way to detect this?

No, in general.

The stack size is platform dependent. Typically, the operating system determines the size of the stack. This way you can check your OS ( ulimit -s on linux) to find out how much stack memory is allocated for your program.

If your compiler supports stackavail() , you can check it out. It is better to use the allocated memory heap in situations where you are not sure whether you will exceed the stack limit.

+1
source

Source: https://habr.com/ru/post/918340/


All Articles