Bad Address from Speed Optimized Code 
Author Message
 Bad Address from Speed Optimized Code

I just upgraded from .NET 2002 to .NET 2003 and my program
that ran in the former does not run now. The problem shows
up as a runtime error trying to go to a bogus address
0x3ff00000 only when I optimize for speed in the Release
Mode.  Debug works and Release, non-optimized, works fine.

I have a simple Windows MFC app calling a C library that I
build separately (it is the popular FFTW freeware from
MIT). Everything is linked statically, multithreaded.  I
tried many different settings but only speed optimization
seemed to make a difference.

The user clicks on a menu "run" option, calling a
handler, "ProcessImages", that does some initializing,
prompts the user for a directory, then
calls "ProcessImage" on each file in the
directory.  "ProcessImage" makes the offending
call, "rfftwnd_one_real_to_complex":

int CImageDoc::ProcessImages() {

        if (!m_isInitialized) return 0;
        m_isRunning = 1;

        // pick directory holding image files to be
processed
        CString text = _T("Select source directory");
        RequestDir( m_path, text);
        if (m_path.IsEmpty() || !SetCurrentDirectory(
(LPCTSTR)m_path)) {
                AfxMessageBox( _T("Unable to find source
directory"));
                return 0;
                }

        // pick directory to hold output files
        text = _T("Select target directory");
//      m_trgPath = m_path;
        RequestDir( m_trgPath, text);
        if (m_trgPath.IsEmpty() || !SetCurrentDirectory(
(LPCTSTR)m_trgPath)) {
                AfxMessageBox( _T("Unable to find target
directory"));
                return 0;
                }

        // read the file names
        FindFileNames( (LPCTSTR)_T("*.*"));

        // create FFTW plan
        rfftwnd_plan plan =  rfftw2d_create_plan(
IMGDOC_IMAGESIZE, IMGDOC_IMAGESIZE,
                                 FFTW_REAL_TO_COMPLEX,
FFTW_ESTIMATE); // ****** THIS CALL TO THE LIBRARY IS OK
*********

        // iterate over the files
        int isOdd = ((int)IMGDOC_IMAGESIZE) % 2;
        for (int i = 0; i < m_imageCount; i++) {
                // load file
                LoadImageFile( i);
                ProcessImage( plan, isOdd);
                }

        // find azimuthal avg and store result
        if (!FindAzimuthalAverage( isOdd)) return 0;
        if (!StoreOutputFile()) return 0;

        // clean up
        rfftwnd_destroy_plan( plan);
        return 1;

        }

void CImageDoc::ProcessImage( rfftwnd_plan& plan, int
isOdd) {

        // calculate the forward 2D FFT, unscaled
        rfftwnd_one_real_to_complex( plan, m_pImage,
m_pFFT); // ************* THIS IS THE OFFENDING CALL ******

        // update m_pAvgFFT2[][] on left half, as well as
the center, of image
        int i, j;
        int hlf = (int)(IMGDOC_IMAGESIZE)/((int)2);
        int ival = hlf + isOdd;
        int indx;
        fftw_real  cr, ci;
        // assign left half, as well as the center, of
image
        for (i = indx = 0; i < IMGDOC_IMAGESIZE; i++) {
                for (j = 0; j < ival; j++) {
                        cr = m_pFFT[ indx].re;
                        ci = m_pFFT[ indx].im;
                        m_pAvgFFT2[ i][ j] += (cr * cr +
ci * ci);
                        indx++;
                        }
                if (!isOdd) indx++;
                }

        }

void CImageDoc::RequestDir( CString& path, CString& text) {

        CSelectDirDlg dlg;
        dlg.m_pPath = &path;
        dlg.m_pText = &text;
        if (dlg.DoModal() == IDOK) {
                int indx = path.ReverseFind( _T('\\'));
                int len  = path.GetLength()/sizeof(TCHAR);
                if (indx != (len - 1)) path += _T('\\');
                }

        }

int CImageDoc::FindFileNames( LPCTSTR pSuffix) {

  WIN32_FIND_DATA fd;
  CString path = m_path + pSuffix;
  HANDLE hFind = ::FindFirstFile( (LPCTSTR)path, &fd);
  if (hFind != INVALID_HANDLE_VALUE) {
    do {
        if (!(fd.dwFileAttributes &
FILE_ATTRIBUTE_DIRECTORY)) {
          if (m_pFilenameList[ m_imageCount] != NULL)
delete [] m_pFilenameList[ m_imageCount];
          m_pFilenameList[ m_imageCount] = new TCHAR[
fd.nFileSizeLow + 1];
          if (m_pFilenameList[ m_imageCount] == NULL)
return 0;
          LPTSTR pName = m_pFilenameList[ m_imageCount];
          int i = 0;
          while (pName[ i] = fd.cFileName[ i])  i++;
          m_imageCount++;
          }
        } while (::FindNextFile( hFind, &fd) &&
(m_imageCount < IMGDOC_MAXFILE));
    ::FindClose( hFind);
    }

  return 1;

  }

int CImageDoc::LoadImageFile( int fileIndx) {

        // open the file
        CString path = m_path + m_pFilenameList[ fileIndx];
        CFile file;
        if (!file.Open( path, CFile::modeRead))
        return 0;
        int size = file.GetLength();
        if (size != (IMGDOC_PIXELCOUNT * 2)) return 0;
        //  PROJECT SPECIFIC

        // alloc space to hold file data
        BYTE* pb = new BYTE[ IMGDOC_PIXELCOUNT * 2];
        if (pb == NULL) return 0;

        // read the file
        int bytesRead;
        try {
                bytesRead = file.Read( (void*)pb, size);
        // in BYTES
                }
        catch (CFileException *err) {
                err->ReportError();
                err->Delete();
                delete [] pb;
                return 0;
                }
        file.Close();
        if (bytesRead != size) { delete [] pb;  return 0; }

        // load m_pImage
        int i, j, indx, indx2;
        WORD wval;
        BYTE* pbw = (BYTE*)&wval;
        for (i = indx = indx2 = 0; i < IMGDOC_IMAGESIZE;
i++)
                for (j = 0;  j < IMGDOC_IMAGESIZE; j++)  {
                        pbw[ 1] = pb[ indx2++];
                        pbw[ 0] = pb[ indx2++];
                        m_pImage[ indx++]  =  (fftw_real)
wval;
                        }

        // clean up
        delete [] pb;
        return 1;

        }

What is odd is that I can comment out the offending
library function call, rfftwnd_one_real_to_complex, and it
works, but when I put it back in I get the address read
error well before the call is even made.  I know this
because the user is supposed to be prompted to select a
directory before the call is made but the error occurs
before the prompting dialogue box appears.

I wonder if loading .NET 2003 without first removing .NET
2002 could be a problem?  I thought it would prompt me to
remove the old version but it never did.

Anyway, this has me stumped and I do not know how to
proceed further to resolve this problem.  It is important
to me that this code run as fast as possible, so any help
would be greatly appreciated!

Thank you,
Paul  



Sun, 20 Nov 2005 07:10:01 GMT  
 Bad Address from Speed Optimized Code

Quote:
>I just upgraded from .NET 2002 to .NET 2003 and my program
>that ran in the former does not run now. The problem shows
>up as a runtime error trying to go to a bogus address
>0x3ff00000 only when I optimize for speed in the Release
>Mode.  Debug works and Release, non-optimized, works fine.
>What is odd is that I can comment out the offending
>library function call, rfftwnd_one_real_to_complex, and it
>works, but when I put it back in I get the address read
>error well before the call is even made.  I know this
>because the user is supposed to be prompted to select a
>directory before the call is made but the error occurs
>before the prompting dialogue box appears.

Paul,

Have you tried debugging your optimized release version to pin-point
the problem?

Quote:
>I wonder if loading .NET 2003 without first removing .NET
>2002 could be a problem?

I don't think so.

Quote:
>I thought it would prompt me to remove the old version but it never did.

The 2 versions should be able to co-exist.

Dave
--
MVP VC++ FAQ: http://www.mvps.org/vcfaq



Sun, 20 Nov 2005 16:40:20 GMT  
 Bad Address from Speed Optimized Code

Quote:
>Have you tried debugging your optimized release version
to pin-point
>the problem?

Hi Dave.  Although I have a masters degree in computer
science and some Phd-level courses as well (mostly in
theory), I am what you might call a reluctant programmer -
if I could hire a real programmer I would stick to
algorithm design, which is what I really do.  The extent
of my debugging expertise is to use debugging mode to step
through code and find errors.  I have no experience
debugging Release code outside the de{*filter*}.  Can you give
me some pointers in this regard?  Are there tools for this
purpose?  How do I proceed?  

Quote:
>The 2 versions should be able to co-exist.

I don't see much point in having 2 versions taking up disk
space (unless I cannot resolve this optimization issue and
have to go back to 2002 ver.), particularly since projects
loaded into 2003 ver can no longer be read in the 2002
ver.  Can I uninstall the old version after loading the
new, without impairing the latter?

Thank you for your assistance Dave!

Paul



Sun, 20 Nov 2005 22:31:57 GMT  
 Bad Address from Speed Optimized Code

Quote:
> The extent
>of my debugging expertise is to use debugging mode to step
>through code and find errors.

That's really all you have to do now to pinpoint it.

Quote:
> I have no experience
>debugging Release code outside the de{*filter*}.  Can you give
>me some pointers in this regard?
>  Are there tools for this
>purpose?  How do I proceed?  

See "Turn on Generation of Debug Information for the Release Build" or
"Debugging a Release Build" in the MSDN help and use the IDE de{*filter*}
to step through to the problem area.

Debugging an optimized build is not as straightforward as a
non-optimized build because the de{*filter*} may appear to jump around the
code somewhat, and local variables won't necessarily be what you think
they should be. A little bit of assembly knowledge can be useful
especially if the problem really is an optimization issue - rather
than a coding problem that only shows up with a particular set of
optimizations.

Another thing to check (if you're not already using them) is to ensure
that you use the run-time compiler options in your debug build - these
can identify some problems in the debug build that don't normally show
up.

Quote:
>Can I uninstall the old version after loading the
>new, without impairing the latter?

Yes, I removed 2002 after installing 2003, and I don't recall having
any problems.

Dave
--
MVP VC++ FAQ: http://www.*-*-*.com/



Sun, 20 Nov 2005 23:20:30 GMT  
 Bad Address from Speed Optimized Code
Ok, I'll give it a go. If I find anything of interest or
attain a new state of confusion on a higher operating
plane I will start a new post.

Thanks again for your help, Dave.

Paul



Mon, 21 Nov 2005 00:49:11 GMT  
 Bad Address from Speed Optimized Code

--------------------

Quote:
>Content-Class: urn:content-classes:message







Quote:
>Subject: Re: Bad Address from Speed Optimized Code
>Date: Wed, 4 Jun 2003 09:49:11 -0700
>Lines: 7

>MIME-Version: 1.0
>Content-Type: text/plain;
>    charset="iso-8859-1"
>Content-Transfer-Encoding: 7bit
>X-Newsreader: Microsoft CDO for Windows 2000
>Thread-Index: AcMquTl5p64SEGMTRVmKvFvxgO/+Dw==
>X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300
>Newsgroups: microsoft.public.dotnet.languages.vc
>Path: cpmsftngxa06.phx.gbl
>Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.vc:24602
>NNTP-Posting-Host: TK2MSFTNGXA11 10.40.1.163
>X-Tomcat-NG: microsoft.public.dotnet.languages.vc

>Ok, I'll give it a go. If I find anything of interest or
>attain a new state of confusion on a higher operating
>plane I will start a new post.

>Thanks again for your help, Dave.

>Paul

If you could provide a standalone, reproducible test case then I would be
happy to take a look and see if this an optimizer bug.

--
Ian Bearman, Microsoft Visual C++ Team
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm



Tue, 22 Nov 2005 02:55:59 GMT  
 Bad Address from Speed Optimized Code

Quote:
>If you could provide a standalone, reproducible test case
then I would be
>happy to take a look and see if this an optimizer bug.

Hi Ian,

I did what David suggested and generated database info in
my Release build and found that when I try to optimize,
NONE of my basic Windows class pointers are valid!  

This has nothing to do with this particular application.  
I created a bare-bones app as follows:  
  select File->New->Blank Soln->Vis C++ Proj->MFC->MFC App
In the Wizard set:
  Multiple Docs, MFC Standard, Doc/View Arch Support
  No Compound Doc Support
  No Database Support
  Check Context-Sensitive Support - HTML
  Check Printing
  Check ActiveX Controls
  Check Common Control Manifest
  Set the base view class to CScrollView

On the Property Page I activate the Release Configuration
with the Linker generating debug info, and in the source
code I set a breakpoint in the App::InitInstance()
function.  

I tried all sorts of combinations but the only one that
causes problems is when I set
  Config Prop->C/C++->Optimization
to Maximize Speed or Full Optimization (I have not tried
Minimize Size but I am guessing that would be no
different).  

When I turn on Optimization in this manner and set a
breakpoint in the App::InitInstance() function,
the "App::this" pointer is NULL! And if I set other
breakpoints I find that all of the other "this" pointers,
such as CAppDoc and CAppView, are invalid as well.

When I "disable" Optimization and Rebuild Soln, then
everything appears fine - the "this" pointers are
apparently properly initialized once again!

Paul



Wed, 23 Nov 2005 04:09:52 GMT  
 Bad Address from Speed Optimized Code

Quote:
>I did what David suggested and generated database info in
>my Release build and found that when I try to optimize,
>NONE of my basic Windows class pointers are valid!  

Paul,

As I tried to explain, you can't necessarily trust the values of
things reported by the de{*filter*} in an optimised build. Take them all
with a pinch of salt.

Can you reproduce a problem in a bare-bones application?

Dave
--
MVP VC++ FAQ: http://www.*-*-*.com/



Wed, 23 Nov 2005 04:53:50 GMT  
 Bad Address from Speed Optimized Code

Quote:
>Can you reproduce a problem in a bare-bones application?

>Dave

Ok, while trying to distill it all down I found the
problem:

COLORREF ShadeColor( COLORREF color) {
  ....
  double ratio[3];
  int mean = FindBrightnessScaling( (double*)ratio, (int*)
c3, min, max);
  ....
  }

int FindBrightnessScaling( double* ratio, int* c3, int
min, int max) {

  for (int i=0; i < 3; i++)
      ratio[3] = 1;  //******* writing past end of array!!
  ....
  return mean;
  }

I presume that an Optimized build would be most
susceptible to this stomping on the function return
address?

I looked at this a thousand times and did not catch this.

Dave and Ian, I owe you both an apology for my being
stupid.  I am guessing that I could have turned on a build
option to check for this sort of thing?!

Oh well, I did learn a few things and hopefully I will be
more aware of situations of this sort in the future. Thank
you both for your help and your concern.

Respectfully,
Paul



Thu, 24 Nov 2005 06:18:09 GMT  
 Bad Address from Speed Optimized Code

Quote:

>> Can you reproduce a problem in a bare-bones application?

>> Dave

> Ok, while trying to distill it all down I found the
> problem:

> COLORREF ShadeColor( COLORREF color) {
>   ....
>   double ratio[3];
>   int mean = FindBrightnessScaling( (double*)ratio, (int*)
> c3, min, max);
>   ....
>   }

> int FindBrightnessScaling( double* ratio, int* c3, int
> min, int max) {

>   for (int i=0; i < 3; i++)
>       ratio[3] = 1;  //******* writing past end of array!!
>   ....
>   return mean;
>   }

> I presume that an Optimized build would be most
> susceptible to this stomping on the function return
> address?

Compiling with /RTCs will sometimes catch this kind of error.

Quote:

> I looked at this a thousand times and did not catch this.

They can be hard to spot - which is the main reason why raw arrays are evil.

Quote:

> Dave and Ian, I owe you both an apology for my being
> stupid.  I am guessing that I could have turned on a build
> option to check for this sort of thing?!

> Oh well, I did learn a few things and hopefully I will be
> more aware of situations of this sort in the future. Thank
> you both for your help and your concern.

> Respectfully,
> Paul

-cd


Thu, 24 Nov 2005 07:16:49 GMT  
 Bad Address from Speed Optimized Code

Quote:
>Ok, while trying to distill it all down I found the
>problem:
>  ....
>      ratio[3] = 1;  //******* writing past end of array!!
>I presume that an Optimized build would be most
>susceptible to this stomping on the function return
>address?

It will depend on many things, I don't think you can say one way or
another.

As Carl said, the new run-time debug checks may well have found this
problem for you in a debug build. If you've not used them I definitely
recommend you do - the compiler should have had them years ago!

Quote:
>I looked at this a thousand times and did not catch this.

We all do it. The more you look at something, the more you can
convince yourself it's right.

Cheers
Dave
--
MVP VC++ FAQ: http://www.mvps.org/vcfaq



Thu, 24 Nov 2005 07:49:18 GMT  
 
 [ 12 post ] 

 Relevant Pages 

1. How to optimize execution speed of code ??

2. How to speed optimize c/c++ code

3. Problems with for speed optimized code

4. Problems with for speed optimized code

5. how to optimize this code for speed

6. Optimizing random number generator (was Re: Optimizing code for tests)

7. Throwing exceptions in ATL dll with optimize for SPEED causes Access Violation

8. Speed/safety optimizing recomendation.

9. Problem with Optimize for speed in VC++ 5.0

10. Optimizing C compiler(speed)

11. Optimizing speed using inline assembly fails - Why?

12. BUG: Optimize for Speed in Release builds

 

 
Powered by phpBB® Forum Software