The bug occurs when returning from a function call.
here is the broken disassembly...
template <class PixelType>
inline triple<typename
BasicImage<PixelType>::const_traverser,
typename
BasicImage<PixelType>::const_traverser,
typename
BasicImage<PixelType>::ConstAccessor>
srcImageRange(BasicImage<PixelType> const & img)
{
00412B70 push ebp
00412B71 mov ebp,esp
00412B73 sub esp,54h
00412B76 push ebx
00412B77 push esi
00412B78 push edi
return triple<typename
BasicImage<PixelType>::const_traverser,
typename
BasicImage<PixelType>::const_traverser,
typename
BasicImage<PixelType>::ConstAccessor>(img.upperLeft(),
img.lowerRight(),
img.accessor());
00412B79 mov ecx,dword ptr [img]
00412B7C call vigra::BasicImage<float>::accessor
(4111E0h)
00412B81 mov byte ptr [ebp-51h],al
00412B84 lea eax,[ebp-51h]
00412B87 push eax
00412B88 lea ecx,[ebp-50h]
00412B8B push ecx
00412B8C mov ecx,dword ptr [img]
00412B8F call vigra::BasicImage<float>::lowerRight
(41124Eh)
00412B94 push eax
00412B95 lea edx,[ebp-48h]
00412B98 push edx
00412B99 mov ecx,dword ptr [img]
00412B9C call vigra::BasicImage<float>::upperLeft
(411154h)
00412BA1 push eax
00412BA2 mov ecx,dword ptr [ebp+8]
00412BA5 call
vigra::triple<vigra::ConstBasicImageIterator<float,float *
*>,vigra::ConstBasicImageIterator<float,float *
*>,vigra::StandardConstValueAccessor<float>
>::triple<vigra::ConstBasicImageIterator<float,float *
*>,vigra::ConstBasicImageIterator<float,float *
*>,vigra::StandardConstValueAccessor<float> > (411249h)
00412BAA mov eax,dword ptr [ebp+8]
}
00412BAD pop edi
00412BAE pop esi
00412BAF pop ebx
00412BB0 mov esp,ebp
00412BB2 pop ebp
00412BB3 ret
note that instructions
00412B84 lea eax,[ebp-51h]
00412B87 push eax
should come before
00412B7C call vigra::BasicImage<float>::accessor
Since the ordering is wrong, the call to
vigra::BasicImage<float>::accessor returns the value
stored in edi, which was previously pushed onto the stack
at the start of the call. The value in edi has nothing to
do with [ebp-51h], which is where the real data should
be. This is a real showstopper.
When enabled, the code trips the Run Time error checking
function because esp and ebp are not comparable at the end
of the function call. The error suggests that the calling
conventions were mismatched, but this is false.
The assembly code can be corrected by adding an explicit
constructor to one of the C++ classes involved. The
correct code generated is this:
template <class PixelType>
inline triple<typename
BasicImage<PixelType>::const_traverser,
typename
BasicImage<PixelType>::const_traverser,
typename
BasicImage<PixelType>::ConstAccessor>
srcImageRange(BasicImage<PixelType> const & img)
{
00412B70 push ebp
00412B71 mov ebp,esp
00412B73 sub esp,54h
00412B76 push ebx
00412B77 push esi
00412B78 push edi
return triple<typename
BasicImage<PixelType>::const_traverser,
typename
BasicImage<PixelType>::const_traverser,
typename
BasicImage<PixelType>::ConstAccessor>(img.upperLeft(),
img.lowerRight(),
img.accessor());
00412B79 lea eax,[ebp-51h]
00412B7C push eax
00412B7D mov ecx,dword ptr [img]
00412B80 call vigra::BasicImage<float>::accessor
(4111E0h)
00412B85 push eax
00412B86 lea ecx,[ebp-50h]
00412B89 push ecx
00412B8A mov ecx,dword ptr [img]
00412B8D call vigra::BasicImage<float>::lowerRight
(41124Eh)
00412B92 push eax
00412B93 lea edx,[ebp-48h]
00412B96 push edx
00412B97 mov ecx,dword ptr [img]
00412B9A call vigra::BasicImage<float>::upperLeft
(411154h)
00412B9F push eax
00412BA0 mov ecx,dword ptr [ebp+8]
00412BA3 call
vigra::triple<vigra::ConstBasicImageIterator<float,float *
*>,vigra::ConstBasicImageIterator<float,float *
*>,vigra::StandardConstValueAccessor<float>
>::triple<vigra::ConstBasicImageIterator<float,float *
*>,vigra::ConstBasicImageIterator<float,float *
*>,vigra::StandardConstValueAccessor<float> > (411249h)
00412BA8 mov eax,dword ptr [ebp+8]
}
00412BAB pop edi
00412BAC pop esi
00412BAD pop ebx
00412BAE mov esp,ebp
00412BB0 pop ebp
00412BB1 ret
If this bug is not corrected, our company may be forced to
abandon VC7.1 in favor of gcc. I can send the bug to
whomever it may concern.