Hi there,

I believe I've found an issue with a specific combination of object
instantiations and the alloca() function. It appears that the compiler
miscalculates the placement of ESI on the stack, so in a debug build, the
__RTC_CheckEsp() stack checker function throws up the following warning:

"Run-Time Check Failure #0 - The value of ESP was not properly saved across
a function call. This is usually a result of calling a function declared
with one calling convention with a function pointer declared with a different
calling convention."

I've attached the code below and it should be reproducible by creating a new
win32 c++ project and just running and building it in debug.

Thanks for your attention. If you can confirm my results, please let me
know. I've tested it against the original VC++ 2003 and similar code causes
the same issue with SP1. I'll update when I get to try it on VS2005.

Rich

/////////////////////////

#include <malloc.h>
#include <windows.h>

class ClassWithDestructor
{
public:
~ClassWithDestructor() {} // Destructor needed
};

class AlignedMember
{
__declspec(align(32)) int a; // Needs an aligned member
public:
AlignedMember() {} // Constructor needed
};

class Application
{
public:
virtual bool Application::render() // Needs to be virtual
{
ClassWithDestructor classWithDestructor;
int *myInt = (int *)alloca(sizeof(int));
AlignedMember alignedMember;
return true;
}
bool callRender() { return render(); } // Needs a wrapper to the virtual
virtual ~Application() {}
};

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
Application application;
return application.callRender();
}

Re: Compiler bug with aligned members in virtuals + alloca() in VS2003 by Carl

Carl
Fri Oct 20 15:49:25 CDT 2006

"RichForster" <RichForster@discussions.microsoft.com> wrote in message
news:4C6986A1-4006-4219-A96D-7DF2CCD07CC6@microsoft.com...
> Hi there,
>
> I believe I've found an issue with a specific combination of object
> instantiations and the alloca() function. It appears that the compiler
> miscalculates the placement of ESI on the stack, so in a debug build, the
> __RTC_CheckEsp() stack checker function throws up the following warning:
>
> "Run-Time Check Failure #0 - The value of ESP was not properly saved
> across
> a function call. This is usually a result of calling a function declared
> with one calling convention with a function pointer declared with a
> different
> calling convention."
>
> I've attached the code below and it should be reproducible by creating a
> new
> win32 c++ project and just running and building it in debug.
>
> Thanks for your attention. If you can confirm my results, please let me
> know. I've tested it against the original VC++ 2003 and similar code
> causes
> the same issue with SP1. I'll update when I get to try it on VS2005.

Thanks for the complete repro program - that always helps a lot.

I tried your code with 2005 and couldn't reproduce an error. You didn't
indicate the exact combination of compiler options/switches that you were
using, so I tried a variety of combinations, none of which produced the
runtime error you're seeing. The one I didn't try was to create an IDE
project in 2005 and try that, nor did I try to determine the settings that a
2003 IDE project would have used - there are just too many variables. If
you can post back with the exact compiler options that were used in your
build, I'd be happy to try that on 2005 and let you know the outcome.

-cd



Re: Compiler bug with aligned members in virtuals + alloca() in VS by RichForster

RichForster
Sat Oct 21 03:06:01 CDT 2006

"Carl Daniel [VC++ MVP]" wrote:

> Thanks for the complete repro program - that always helps a lot.
>
> I tried your code with 2005 and couldn't reproduce an error. You didn't
> indicate the exact combination of compiler options/switches that you were
> using, so I tried a variety of combinations, none of which produced the
> runtime error you're seeing. The one I didn't try was to create an IDE
> project in 2005 and try that, nor did I try to determine the settings that a
> 2003 IDE project would have used - there are just too many variables. If
> you can post back with the exact compiler options that were used in your
> build, I'd be happy to try that on 2005 and let you know the outcome.
>
> -cd

Thanks for taking the time to check it out. As I said, I've only seen this
problem with 2003 and not had a chance to test 2005 yet. I think its entirely
possible that its been fixed in the 2005 compiler, but where would that leave
2003 users?

I've attached the vcproj file from 2003 so you can cut'n'paste it into a new
project, or at least see the settings I was using.

Thanks again for your help,

Kindest regards,

Rich

<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="SSECompilerBug"
ProjectGUID="{FDEAC455-9ECB-4039-A917-5B10BA060CC2}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/SSECompilerBug.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/SSECompilerBug.pdb"
SubSystem="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\SSECompilerBug.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>


Re: Compiler bug with aligned members in virtuals + alloca() in VS by RichForster

RichForster
Mon Oct 23 04:04:01 CDT 2006

> Thanks for taking the time to check it out. As I said, I've only seen this
> problem with 2003 and not had a chance to test 2005 yet. I think its entirely
> possible that its been fixed in the 2005 compiler, but where would that leave
> 2003 users?
>
> I've attached the vcproj file from 2003 so you can cut'n'paste it into a new
> project, or at least see the settings I was using.
>
> Thanks again for your help,
>
> Kindest regards,
>
> Rich
>

Hi again,

Back at work today, I was able to convert my project from 2003 to 2005 and
try the code. It appears that the bug has been fixed in the 2005 C++
compiler. I guess this leaves it as a 2003 compiler bug, which was still
present with SP1. How do these typically get handled? I assume there's plenty
of 2003 users who could have the same problem. In the short term is there a
version defined that I can check to enable features in VS2005? i.e. #if
MSC_VER > XXX ? Then, does anyone know what the next step is for submitting
this as a bug to Microsoft?

Thanks in advance for your help,

Rich

Re: Compiler bug with aligned members in virtuals + alloca() in VS by Alex

Alex
Mon Oct 23 06:50:02 CDT 2006

RichForster wrote:
> Back at work today, I was able to convert my project from 2003 to 2005 and
> try the code. It appears that the bug has been fixed in the 2005 C++
> compiler. I guess this leaves it as a 2003 compiler bug, which was still
> present with SP1. How do these typically get handled? I assume there's plenty
> of 2003 users who could have the same problem. In the short term is there a
> version defined that I can check to enable features in VS2005? i.e. #if
> MSC_VER > XXX ?

Why do you need `alloca'? From the short sample you provided
it's not obvious that `alloca' is necessary. It can be
easily replaced by regular `operator new':

virtual bool Application::render()
{
ClassWithDestructor classWithDestructor;
std::auto_ptr<int> myInt(new int);
AlignedMember alignedMember;

return true;
}

> Then, does anyone know what the next step is for submitting
> this as a bug to Microsoft?

There is Feedback Connections at MS site. However, I didn't
find anything for VS2003.NET.

"Available Connections"
http://connect.microsoft.com/availableconnections.aspx


HTH
Alex

Re: Compiler bug with aligned members in virtuals + alloca() in VS by RichForster

RichForster
Tue Oct 24 03:33:01 CDT 2006

> Why do you need `alloca'? From the short sample you provided
> it's not obvious that `alloca' is necessary. It can be
> easily replaced by regular `operator new':
>
> virtual bool Application::render()
> {
> ClassWithDestructor classWithDestructor;
> std::auto_ptr<int> myInt(new int);
> AlignedMember alignedMember;
>
> return true;
> }
>
> > Then, does anyone know what the next step is for submitting
> > this as a bug to Microsoft?
>
> There is Feedback Connections at MS site. However, I didn't
> find anything for VS2003.NET.
>
> "Available Connections"
> http://connect.microsoft.com/availableconnections.aspx
>
>
> HTH
> Alex

Hi Alex,

Thanks for your feedback.

I'll totally agree in the contrived example, I don't need alloca() but in
real world situations, the overhead of operator new is excessive relative to
the locality of the allocation and the lifetime of the array. I use the
simple alloca() in the example since it was the minimum case that broke the
compiler.

The connections site doesn't really give me any options for VS 2003/.Net
either. This is pretty much what I found when I was looking into posting this
bug, that there's not a lot of options when it comes to reporting issues with
the older version of VS. For now I'll have to use MSC_VER >= 1400 to check
for VS 2005 to enable code that would cause issues with 2003.

Thanks again,

Rich

Re: Compiler bug with aligned members in virtuals + alloca() in VS by Alex

Alex
Tue Oct 24 04:27:51 CDT 2006

RichForster wrote:
> I'll totally agree in the contrived example, I don't need alloca() but in
> real world situations, the overhead of operator new is excessive relative to
> the locality of the allocation and the lifetime of the array. I use the
> simple alloca() in the example since it was the minimum case that broke the
> compiler.

That definitely requires measuring before you draw any
conclusions. Most of the time `operator new' doesn't
allocate memory, it just marks available chunk as taken in
preallocated list of memory chunks. So, roundtrip to CRT and
back is very cheap. At the same time, `_alloca' can cause
page fault while probing stack for required amount of bytes.
Such page fault, being handled by system, will cost much
more than regular call to `new'.

Here's quite interesting research regarding allocations speed:

"Calkins. Memory Allocation Methods in Multithreaded
Programming in C++ Under Windows NT an Applied Intelligence
Whitepaper, May 2000"
http://www.lotn.org/~calkinsc/papers/memorywp.pdf

Re: Compiler bug with aligned members in virtuals + alloca() in VS by RichForster

RichForster
Tue Oct 24 15:19:02 CDT 2006

"Alex Blekhman" wrote:
>
> That definitely requires measuring before you draw any
> conclusions. Most of the time `operator new' doesn't
> allocate memory, it just marks available chunk as taken in
> preallocated list of memory chunks. So, roundtrip to CRT and
> back is very cheap. At the same time, `_alloca' can cause
> page fault while probing stack for required amount of bytes.
> Such page fault, being handled by system, will cost much
> more than regular call to `new'.
>
> Here's quite interesting research regarding allocations speed:
>
> "Calkins. Memory Allocation Methods in Multithreaded
> Programming in C++ Under Windows NT an Applied Intelligence
> Whitepaper, May 2000"
> http://www.lotn.org/~calkinsc/papers/memorywp.pdf

Hi Alex,

That is an interesting paper. In the original case I was looking at, the use
of new also may have the side effect of fragmenting the heap since the
requirement of the alloca() was to allocate temporary memory. The cost of an
alloca() should be little more than an inline manipulation of the stack or
frame pointers. Its just a shame that the alloca is incompatible with the
alignment constraint on the struct member. I am going to need a workaround
tho, so in the longer term, I guess I may end up with a solution based on new.

Cheers,

Rich

Re: Compiler bug with aligned members in virtuals + alloca() in VS by Alex

Alex
Wed Oct 25 04:02:53 CDT 2006

RichForster wrote:
> In the original case I was looking at, the use
> of new also may have the side effect of fragmenting the heap since the
> requirement of the alloca() was to allocate temporary memory. The cost of an
> alloca() should be little more than an inline manipulation of the stack or
> frame pointers. Its just a shame that the alloca is incompatible with the
> alignment constraint on the struct member. I am going to need a workaround
> tho, so in the longer term, I guess I may end up with a solution based on new.

The point is that `new' rarely causes actual allocation.
Most of the time it uses preallocated list of memory chunks.
Fragmentation of that list originates rather from usage
patterns than from requested chunk size. If your calls to
`new' resemble LIFO pattern in some way, then fragmentation
will be minimal. In any way, without measuring actual code
in real life conditions it's impossible to predict which way
of allocation is faster. You should measure it first before
investing any thoughts in the problem.

Re: Compiler bug with aligned members in virtuals + alloca() in VS by RichForster

RichForster
Wed Oct 25 11:38:02 CDT 2006

"Alex Blekhman" wrote:
> The point is that `new' rarely causes actual allocation.
> Most of the time it uses preallocated list of memory chunks.
> Fragmentation of that list originates rather from usage
> patterns than from requested chunk size. If your calls to
> `new' resemble LIFO pattern in some way, then fragmentation
> will be minimal. In any way, without measuring actual code
> in real life conditions it's impossible to predict which way
> of allocation is faster. You should measure it first before
> investing any thoughts in the problem.

I agree. In the code I'm actually working on, I'm unable to do any kind of
performance testing in VS 2003 since the use of alloca() in a similar case as
above causes it to crash due to broken code generation. I appreciate all of
your feedback, and as I said, if the 2003 compiler can't be fixed, then new
is the only solution. My perfect solution would be a working compiler :)

Cheers,

Rich