Search

runtime stack corruption message using VC8 64bit - by warnold

Closed
as Fixed Help for as Fixed

1
Sign in to vote
0
Sign in to vote
Sign in
to vote
Type: Bug
ID: 113800
Opened: 1/12/2006 11:06:02 AM
Access Restriction: Public
0
Workaround(s)
0
User(s) can reproduce this bug
The attached Visual Studio 2005 project when compiled 64bit with stack checking enabled. Will report a stack corruption on return from the function. There is no code in the function, just a calling sequence.

The corruption occurs if the lx and lz variables have memory allocated via alloca function.
If allocated via malloc then there is no corruption report.
Details (expand)
Product Language
English
Version
Visual Studio 2005
Category
Visual C++ Development
Operating System
Windows XP Professional
Operating System Language
US English
Steps to Reproduce
Build attached project. 64bit debug with runtime stack checking enabled

run the program callingseq.exe
Actual Results
Stack corruption message at runtime
Expected Results
no message, clean return
File Attachments
1 attachments
Sign in to post a comment.
Posted by Microsoft on 1/12/2006 at 4:06 PM
The bug is now assigned to one of our teams to take a look.

Thanks,
Ayman Shoukry
Program Manager
VC++ Team
Posted by Microsoft on 1/16/2006 at 5:02 PM
I don't see attached project. Can you please attach it?
Posted by Microsoft on 1/26/2006 at 1:10 PM
I've verified the failure - it looks like a weird interaction between alloca and the normal RTCs stuff. Thanks for the report. We'll get it fixed.
Posted by Microsoft on 2/1/2006 at 1:26 PM
The Microsoft Sub-status is now "Working on solution"

There are three elements required to hit this bug, all must be present in the same function or method to see the problem. The first is obviously turning on runtime stack checking code generation (/RTCs compile switch) . The second element is a call to alloca, as you have discovered. The final element is a call to another function with > 30 parameters (including 'this'). Our compiler has some x64 machine dependent code that has to fall into special-case handling when there are more than 30 outgoing parameters, and unfortunately the special case code has seen more problems than it should have. In this case there are some invalid assumptions in the generation of the stack checking code for routines that use alloca, and those assmptions fail when there are more than 30 outgoing parameters.

So to workaround this problem, until the fix arrives, you can reduce the number of parameters by creating artificial classes/structs that hold a group of related parameters and thus pass a number of values using only one 'slot' of the 30. Or you can use malloc instead of alloca, or you could create a macro that uses malloc instead of alloca only when running with /RTCs (if leaking memory from the heap during debug runs is tolerable). One technique that might work for you would be to have fixed sized arrays on the stack (as local variables), and use those if the fixed size is large enough. If the pre-determined fixed size isn't large enough for a particular invocation, you could then call malloc (and later free) to create space for the arrays. I hope one of these workarounds meets your interim needs.

Note that this problem does not affect the case where a routine taking more than 30 parameters calls alloca, only when a routine (taking any number of parameters) calls both alloca and another routine with more than 30 parameters.
Posted by Microsoft on 2/1/2006 at 6:22 PM
The Microsoft Sub-status is now "Working on solution"
Posted by Microsoft on 2/7/2006 at 3:58 PM
The Microsoft Sub-status is now "Working on solution"
Posted by Microsoft on 2/7/2006 at 4:22 PM
The Microsoft Sub-status is now "Working on solution"
Posted by Microsoft on 2/8/2006 at 4:14 PM
For this bug to manifest all of the following conditions are required:

1. /RTCs flag on compile command line (or /RTCsu or /RTC1 which both imply /RTCs). This turns on the generation of the run time stack checking code and the associated data tables that contained the error. Note that /RTCs implies and requires /Od.
2. A function calls alloca(), which allocates memory on the stack (as opposed to malloc(), which allocates from the heap). Use of alloca imposes special conditions on the stack checking code.
3. Compilation for an amd64 host. For amd64, code generation utilizes a "floating frame pointer" to reduce the number of instruction bytes generated. This optimization is amd64 specific because it relies on addressing modes only supported by amd64 processors at this time. A "floating frame pointer" points into a statically determined offset in the middle of the stack frame rather than the base of the stack frame as is typical for stack pointers. Note that this optimization is not controlled by the /O flags; it is inherent to the code generation algorithms used for amd64, so it is always on.
4. The same function that calls alloca() also calls another function that takes more than 30 parameters. Space is reserved in the stack frame for "outgoing function parameters", i.e. those passed to routines called by the routine associated with the stack frame. When greater than 30 parameters are passed the size of this area in the stack frame exceeds 0xF0 bytes, and special code generation considerations apply in calculating the offset for the floating frame pointer from the actual frame base address.

When all these conditions apply, the calculation of the offsets of buffers in the frame that should be checked by the run time type checking library routine was in error, and so the run time library was looking in the wrong place in the frame for it's buffer barrier. When the runtime stack check library routine is called upon return from the function the buffer barrier is not found (since the checker was told the wrong place to look for it), and the checking function emits the error message seen.

Numerous workarounds for this bug exist; eliminating any one of the four conditions is sufficient. One likely option would be to reduce the number of parameters by (further) collection of related values into container classes. Another option would be to use preprocessor macro logic to flip back and forth between use of malloc and alloca depending on compilation mode, or to restructure logic to statically allocate buffers instead of using alloca(). For performance intensive code, a guess could be made about the maximum size buffer needed in the majority of cases, and that size buffer could be declared as a local variable, with code logic to select that on-stack buffer unless the particular invocation instance needs a larger one, in which case the fallback would be to malloc() and free().
Posted by Microsoft on 1/17/2007 at 1:44 AM
Thank you for submitting this issue. The bug has been resolved Fixed, and its resolution shipped as part of Visual Studio 2005 Service Pack 1 (SP1).

You can download SP1 at http://msdn.microsoft.com/vstudio/support/vs2005sp1/default.aspx. If installing SP1 does not resolve the issue for you, please reactivate.

Thanks again for your feedback!
-Scott Currie
-DDTFA Program Manager