Sjur Kolberg

Dear list,

I have a problem with the release version of a C++ program, which gives me the following message:

Unhandled exception at 0x7c91888f in RSupdate6.exe: 0xC0000005: Access violation reading location 0x1d00a390.

Visual Studio v. 8.0.50727.42

XP professional 2002 SP 2

Dell Optiplex GX 270, Pentium 4 2.8GHz, 1.5GB RAM

The debug version is OK, and when I debug the release version in VS 2005, it also works OK (although complaining about no debug info).

I have tracked the offending code down to the m_t = new double [ n ]; line in the following member function; it crashes between the two AfxMessageBoxes.

void mhtrace::init(int n, int nburn, int bsize)

{

if (m_t != NULL) delete[] m_t;

AfxMessageBox("init2");

m_t = new double[ n ];

AfxMessageBox("init3");

m_nit = n;

m_nburnin = nburn;

m_blocksize = bsize;

}

This init routine is run from a ReInitialise function when I need to resize the m_t table of several mhtrace objects. The routine may work fine for the first mhtrace objects in a list, and then crash, indicating that I am exceeding some memory limits. I have tried increasing the stack & heap allocation sizes without success. It also fails when n is smaller than the previous size of m_t, thus I am not increasing the overall memory need.

Does anyone recognise these symptoms

Thanks in advance.

Sjur K.




Re: Visual C++ General Access violation in release bulid only

TilakGopi

Hi,

I tried the following code in my sample.I didn't get any error.

[Code language = VC++]

if (m_t != NULL) delete[] m_t;

AfxMessageBox("init2");

m_t = new double[ n ];

AfxMessageBox("init3");

[/Code]

So, it's because memory leak some where else effecting here or some invalid pointer being used some where.

Are u sure that application is crashing at the above line ,every time u run

It should not ,bcoz there is nothing wrong in that block of code.

Better have logs while running.If application crashes at various parts,it's definitely bcoz of memory leack,U need to find out that.

Thanx,

Ch.T.Gopi Kumar.






Re: Visual C++ General Access violation in release bulid only

Jonathan Caves - MSFT

Note: you can build a release build with debug information - you just need to change the project settings to tell the compiler to include debug information. Remember to change both the compiler and the linker settings. Once you have a release build with debug information it should be easier to track down the problem.

Personally I would suspect the delete statement. Where was the memory allocated Was it in the same DLL/EXE or a different DLL What form was the operator new that was used to allocate the memory Do the static and dynamic types of the expression match - in C++ they have to What is the type of m_t






Re: Visual C++ General Access violation in release bulid only

Sjur Kolberg

Hi again, thanks for your help so far.

Only this init() function allocates m_t. The only additional delete [ ] m_t is in the mhtrace destructor.

m_t is declared as double*, it is private, and is set to NULL in the mhtrace constructor.

There is nothing static or const etc in the class mhtrace declaration, and mhtrace does not derive from anything.

I added a try-catch to init(), which now reads:

void mhtrace::init(int n, int nburn, int bsize)

{

try

{

if (m_t != NULL) delete[ ] m_t;

m_t = NULL;

AfxMessageBox("init2");

m_t = new double[ n ];

AfxMessageBox("init3");

}

catch(CException *e)

{

e->ReportError();

e->Delete();

}

catch(...)

{

AfxMessageBox("Unrecognised exception in mhtrace::Init()");

}

m_nit = n;

m_nburnin = nburn;

m_blocksize = bsize;

}

Alas, I don't catch anything, and it still stops between an init2 and an init3 message (after having successfully executed the init() function for several mhtrace objects).

I have indeed included debug info in the release build, but the info I get when stepping through the code is insane. The variables in the Autos and Watch windows take wild values, but the program behaviour indicates that they are OK (a loop iterates the correct number of times, parameter values are suddenly OK when stepping into the function, etc). There are a lot of "Expression cannot be evaluated" messages, and even the _this_ pointer to my CWinApp object is suddenly 0x00000000 for a couple of F10 strokes.

There is a large number of libraries involved, some of them pre-built in what I assume are release versions, not necessarily using VS. The program uses between 130 and 200 MB of memory, depending on data set. It also runs for hours when it successfully starts, so my optimizations favour speed.

I have set the compiler to
Heap reserve 250000000
Heap commit 100000000
Stack reserve 100000000
Stack commit 50000000

Again, things work fine if I run from within the compiler, even using the Start without debugging command. The debug version also works fine when started from the exe file or a shortcut.

Here is the top of the call stack at crash:

ntdll.dll!7c91888f()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!7c918238()
ntdll.dll!7c911c76()
user32.dll!77d4882a()
user32.dll!77d6c2b5()
user32.dll!77d56c72()
user32.dll!77d484fc()
user32.dll!77d485a4()
user32.dll!77d6b00e()
user32.dll!77d6b00e()
user32.dll!77d6b00e()
user32.dll!77d6b00e()
user32.dll!77d4885a()
user32.dll!77d4882a()
user32.dll!77d6b00e()
user32.dll!77d484fc()
user32.dll!77d485a4()
user32.dll!77d5f39a()
> mfc80.dll!DDX_Radio(CDataExchange * pDX=0x16360000, int nIDC=0, int & value=) Line 306 C++
msvcr80.dll!malloc(unsigned int size=3200) Line 163 + 0x63 bytes C
mfc80.dll!operator new(unsigned int nSize=3200) Line 349 + 0x3 bytes C++
RSupdate6.exe!mhtrace::init(int n=400, int nburn=200, int bsize=400) Line 30 + 0x20 bytes C++
RSupdate6.exe!CRSupdate6App::InitTracers(int nit=400, int burnit=485239464, int nblock=12) Line 808 C++
RSupdate6.exe!CRSupdate6App::RunAnalysis(ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char> > > workdir="C:\Sjur\DEMlab\RSupdate6\2003") Line 228 C++
RSupdate6.exe!CRSupdate6Dlg::OnRunButton() Line 555 + 0x47 bytes C++

The arrow indicates where the last available code is, in dlgdata.cpp line 306. The RSupdate6App::InitTracers() calls init in several mhtrace objects with nothing between, and the 78th object fails. My best guess is that I am exceeding some memory limits, but why am I not getting a CMemoryException or other exception

Thanks again :-)

Sjur K.






Re: Visual C++ General Access violation in release bulid only

Jonathan Caves - MSFT

This callstack is weird or at least confusing:

Sjur Kolberg wrote:

ntdll.dll!7c91888f()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!7c918238()
ntdll.dll!7c911c76()
user32.dll!77d4882a()
user32.dll!77d6c2b5()
user32.dll!77d56c72()
user32.dll!77d484fc()
user32.dll!77d485a4()
user32.dll!77d6b00e()
user32.dll!77d6b00e()
user32.dll!77d6b00e()
user32.dll!77d6b00e()
user32.dll!77d4885a()
user32.dll!77d4882a()
user32.dll!77d6b00e()
user32.dll!77d484fc()
user32.dll!77d485a4()
user32.dll!77d5f39a()
> mfc80.dll!DDX_Radio(CDataExchange * pDX=0x16360000, int nIDC=0, int & value=) Line 306 C++
msvcr80.dll!malloc(unsigned int size=3200) Line 163 + 0x63 bytes C
mfc80.dll!operator new(unsigned int nSize=3200) Line 349 + 0x3 bytes C++
RSupdate6.exe!mhtrace::init(int n=400, int nburn=200, int bsize=400) Line 30 + 0x20 bytes C++
RSupdate6.exe!CRSupdate6App::InitTracers(int nit=400, int burnit=485239464, int nblock=12) Line 808 C++
RSupdate6.exe!CRSupdate6App::RunAnalysis(ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char> > > workdir="C:\Sjur\DEMlab\RSupdate6\2003") Line 228 C++
RSupdate6.exe!CRSupdate6Dlg::OnRunButton() Line 555 + 0x47 bytes C++

Why is malloc calling DDX_Radio It could be that callstack is messed up: in which case this can be ignored. You don't call _set_new_handler do you That would cause malloc to make a function call if a memory allocation failed.






Re: Visual C++ General Access violation in release bulid only

Sjur Kolberg

Hello Jonathan,

No, I am not touching call_set_new_handler, nor any other allocation methods than plain new's throughout the program. The call stack would not be the only debugger window that is messed up...

The only weird thing I do is to use OnKickIdle() in my dialog class, because I need the possibility to stop the program without losing everything it has produced so far. The app is dialog based, so App::OnIdle() would never be called. But the program breaks during the initial setup, so OnKickIdle() is not on the call stack yet.

Since the problems I experience (the crash, the weird debugger behaviour and the corrupt call stack) do not seem to hit any previously known bug, my best guess is that they are all caused by the same error. A nasty memory corruption somewhere would explain about everything, wouldn't it I have problems on three different computers, two of which used for building, but VS2005 is installed on the third one, too.

My ordered list of possible errors / fixes now pretty closely resebles my ordered list of things I have little knowledge of (=dislike), like compiler switches, preprocessor definitions/commands, and memory leak tracking. Do you know of any good hands-on newbie guide for those issues

Thanks again for you time :-)

Sjur






Re: Visual C++ General Access violation in release bulid only

Sjur Kolberg

Hello, all!

Thanks to your input, I started looking for errors elsewhere in the code, using two very useful functions well documented in the help system. These are:

_heapchk()

which works both in debug and release builds, and

AfxCheckMemory()

which only works in debug builds. It needs to be enabled at the the start of the program, in MFC typically at the top of the App::InitInstance() function, by:

#ifdef _DEBUG

afxMemDF |= checkAlwaysMemDF;

AfxEnableControlContainer();

#endif

The "#ifdef" and "#endif " lines are only there so I can switch to release build without commenting out those lines (which generate compile errors). The AfxCheckMemory() calls compile also in release configuration, but I don't know what they actually do. I avoid the question by wrapping them in ASSERT()s:

ASSERT(AfxCheckMemory()); // will, if failed, stop execution at this line.

When enabled, AfxCheckMemory will be called at every new or delete, but in my case, it was putting additional AfxCheckMemory()'s all over the code which finally isolated the trivial bug causing the problem: I computed an array index without checking the bounds, and thus accessed illegal memory.

AfxCheckMemory() works because the debug memory allocator places some extra bytes around every heap allocation, and checks if these are changed (which they should never be).

The alternative in release builds is the _heapchk function, which is not (afaik) called automatically at new's and delete's, so you'll have to place calls to it in the code.

if ( _heapchk() != _HEAPOK) MessageBox("_heapchk failed in Dlg line 401"); // or whatever error signal you prefer

I guess it steals some cpu time, so if used frequently, it might be convenient to condition the calls on a #define or a global flag variable, so you can turn them all on or off.

I don't understand how a silly index-out-of-bounds error caused a crash in a totally different function, but at least my program now works also in release bulids. Of course. the error was there in the debug build as well, but ignored due to the extra safety in debug memory allocation.

Thanks again for your help,

Sjur K.






Re: Visual C++ General Access violation in release bulid only

Simple Samples

 Sjur Kolberg wrote:
The alternative in release builds is the  _heapchk function, which is not (afaik) called automatically at new's and delete's, so you'll have to place calls to it in the code.
Another alternative that is used often is to constanly be aware of problems such as this and not allow indexes and pointers to be out of range. Now that you are aware of the possibility you will be more aware and less likely to repeat the problem.

Update: when I originally posted this, some of the above text had a large font size that I did not use. It seems that this forum software really has a mind of it's own about font sizes.

 Sjur Kolberg wrote:
I don't understand how a silly index-out-of-bounds error caused a crash in a totally different function, but at least my program now works also in release bulids. Of course. the error was there in the debug build as well, but ignored due to the extra safety in debug memory allocation.
People often ask about problems such as this and they often don't understand when they are told that the problem is not easily determined and that it is very difficult for us to solve it. Yes, it is very easy for a problem such as this to cause symptoms that are very difficult to relate to the problem. It can save a lot of time when developing software to spend a little time being careful not to allow errors such as invalid index and pointer values.






Re: Visual C++ General Access violation in release bulid only

TilakGopi

Hi Sjur,

yep, atlast u found & solved the problem,that's great job man,

But u shouldn't forget to thank me,for what , see my reply to ur first post.

 

Thanx,

Ch.T.Gopi Kumar.






Re: Visual C++ General Access violation in release bulid only

Sjur Kolberg

Hi again, TilakGopi,

You're right, sorry about that. Your answer both quickly and correctly identified the problem.

Regards, Sjur K :-)






Re: Visual C++ General Access violation in release bulid only

TilakGopi

yep ,

Thanx Sjur.

Best Regards,

Ch.T.Gopi Kumar.