views:

230

answers:

7

Hi,

I wanted to know Why Access Violation occurs for cout And Stack Overflow for printf in the following two code snippets.

I wanted to know why Access Violation for the First code instead of the Stack Overflow.

First Code Which i get Access Violation :

void Test();

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

    Test();

    return 0;
}

Second Code Which i Get Stack Overflow :

void Test();

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

    Test();

    return 0;
}

Answer will be highly appreciated.

Thanks in advance

+3  A: 

Both recursive functions will never stop. It seems that in the second case, no tail optimization is done by the compiler, thus the stack overflow.

swegi
+1  A: 

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

Cătălin Pitiș
+17  A: 

I assume you understand that both functions crash due to exhaustion of the stack after an attempt at infinite recursion. I think what you are asking is: why would the cout example not crash with "Stack Overflow" also?

I do not think the answer has to do with the compiler's detection of tail recursion. If the compiler optimized the recursion away, neither example should crash.

I have a guess as to what is going on. "Stack Overflow" exception is implemented in some cases (e.g., Windows) with a single Virtual Memory "guard page" allocated at the end of the stack. When a stack access hits this guard page a special exception type is generated.

Since the Intel small-granularity page is 4096 bytes long, the guard page stands guard over a range of memory that size. If a function call allocates more than 4096 bytes of local variables, it is possible that the first stack access from it will actually stretch beyond the guard page. The next page can be expected to be unreserved memory, so an access violation would make sense in that case.

Of course you don't explicitly declare any local variables in your example. I would assume that one of the operator<<() methods allocates more than a page of local variables. In other words, that the Access Violation occurs near the beginning of an operator<<() method or some other part of the cout implementation (temporary object constructors, etc.)

Also, even in the function you wrote, the operator<<() implementations are going to need to create some storage for intermediate results. That storage is probably allocated as local storage by the compiler. I doubt it would add up to 4k in your example, though.

The only way to really understand would be to see a stack trace of the access violation to see what instruction is triggering it.

Got a stack trace of the access violation and a disassembly around the area of the faulting opcode?

If you are using the Microsoft C compiler, another possibility is that printf() and your own function were compiled with /Ge and operator<<() was not, or that only your function was compiled with /Ge and factors similar to those described above coincidentally cause the behavior you see -- because in the printf() example the crash happens while your function is being called and in the operator<<() case while you are calling the library.

Heath Hunnicutt
@Heath, " why would the cout example not crash with "Stack Overflow" also?" : YES :). Fantastic Answer
mahesh
Thanks mahesh. Please note also that a similar explanation would apply if you are using Microsoft's /Ge switch, as I added above.
Heath Hunnicutt
Heath, Yeha...Thanks a ton for that :).
mahesh
A: 

Though most people misunderstood your question, the answer is in there.

The second example ends with stack overflow because every function call is pushing a frame onto the stack. Eventually, it gets too big. I agree with Cătălin Pitiș, that it'd be hard to know why the streams example is ending with an access violation without looking at the source.

Wade Williams
Is there any difference between this answer and the Cătălin Pitiș' one?
SadSido
+2  A: 

Both functions trigger a stack overflow on my machine. I am compiling it with MS Visual Studio 2005. Maybe you should specify your platform & compiler, that will help to investigate...

Maybe you compile something in the debug mode and your "cout" implementation includes some checkups, that cannot be performed due to the stack corruption? Maybe your compiler generated the code, that tries to recover from stack overflow and pops an invalid return address? Maybe you are running it on the mobile device? Hard to say without knowing the platform and the compiler.

SadSido
A: 

As for the access violation: if you don't get any successful output, you may simply have a link error. Sometimes the compiler determines there will be a link error and gives you a relevant error message. Sometimes, however, the compiler doesn't figure this out, and you get a runtime error when you actually try to use a method/object in the library.

I had this problem today when linking in pre-built libraries for a project I work on (in Visual Studio). Newer versions of GCC will say things like

Info: resolving std::cout by linking to __imp___ZSt4cout (auto-import) ... This should work unless it involves constant data structures referencing symbols from auto-imported DLLs.

If that autoimport feature screwed up somehow you would also get an access violation.

Max Lybbert
A: 

this remembers me of the problem of the stack being corrupted and the debugger not catching the failing program crashing

Arabcoder