Why access violation for cout and stack overflow for printf

I wanted to know why access violation occurs for cout and Stack for printf in the following two code snippets.

I wanted to know why Access Violation for the first code instead.

The first code I get is Access Violation:

void Test(); void Test() { static int i = 0; cout << i++ << endl; Test(); } int main() { Test(); return 0; } 

The second code from which I get a stack overflow:

 void Test(); void Test() { static int i = 0; printf("%d\n", i++); Test(); } int main() { Test(); return 0; } 

The answer will be highly appreciated.

Thanks in advance

+4
source share
6 answers

I assume that you understand that both functions crash due to the exhaustion of the stack after trying infinite recursion. I think you are asking: why does the cout example not crash with "Stack Overflow" as well?

I do not think the answer is related to the discovery of a tail recursion compiler. If the compiler optimized recursion, none of the examples should crash.

I have an assumption about what is happening. The exception of "stack overflow" is implemented in some cases (for example, Windows) with one "protective page" of virtual memory allocated at the end of the stack. When access to the stack hits this protection page, a special type of exception is created.

Since Intel's low-detail page is 4096 bytes long, the security page is on guard in the range of memory size. If a function call allocates more than 4096 bytes of local variables, it is possible that the first access to the stack from it will actually stretch outside the protective page. It is expected that the next page will be saved unprotected memory, so in this case it makes sense to violate access rights.

Of course, you are not explicitly declaring any local variables in your example. I would suggest that one of the operator <() methods allocates more than a page of local variables. In other words, access violation occurs at the beginning of the operator <() method or some other part of the cout implementation (temporary object constructors, etc.).

In addition, even in the function you wrote, operator <() implementations will need to create some storage for intermediate results. This repository is probably allocated by the compiler as a local repository. I doubt this will add up to 4k in your example.

The only way to figure this out is to see the stack trace of the access violation to see which instruction launches it.

Got a stack trace of access violation and disassembly around the area of ​​the failure operation code?

If you use the Microsoft C compiler, another possibility is that printf () and your own function were compiled with / Ge, and operator <(lt) () was not, or that only your function was compiled with / Ge and factors similarly described above, by default they invoke the behavior that you see - because the printf () example crashes when the function is called, and in the case of the <() operator, when you call the library.

+18
source

Both recursive functions will never stop. It seems that in the second case, the compiler does not optimize the tail, so the stack overflows.

+4
source

Both functions trigger a stack overflow on my machine. I am compiling it using MS Visual Studio 2005. Perhaps you should specify your platform and compiler, which will help to investigate ...

Perhaps you are compiling something in debug mode, and your implementation of "cout" includes some checks that cannot be performed due to stack corruption? Maybe your compiler generated code that is trying to recover from and returns an invalid return address? Maybe you use it on a mobile device? It is hard to say without knowing the platform and compiler.

+2
source

Infinite recursive call for. As for access violation ... it really depends on the implementation of the STL streams. You need to look at the source code of the streams to find out ...

+1
source

Although most people misunderstand your question, the answer is there.

The second example ends with a stack overflow because every function call pushes a frame onto the stack. In the end, it gets too big. I agree with Cătălin Pitiş that it would be difficult to understand why the example of flows ends with an access violation without looking at the source.

0
source

it remembers me about the problem of stack damage, and the debugger did not break the faulty program crash

0
source

All Articles