• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 381
  • Last Modified:

Access Violations after .NET conversion

I have a visual c++ application that was created in VS 6.0.  I have ported this project to VS 8.0 (.net).  I have fixed all the compile-time errors associated with this updating process.  For example, in .net when declaring a variable in a for loop statement, that variable loses scope when the for loop is finished, as in
for (int i = 0; i < 10; i++)  where i would lose scope when the for loop is complete.

So I can now run my program.  However, there is a lot of instability.  The program crashes frequently,  due to Access violations in object arrays.  I get crashes accompanied by error messages like the following:

Unhandled exception at 0x006d543d in MyApp.exe: 0xC0000005: Access violation reading location 0xfeeeff26

According to this error message, I'm trying to access an array slot that does NOT exist.  However, when I check my array size, the array slot in question DOES EXIST.  And when I drag the object into the Watch window, the object DOES EXIST, and has valid data in its member variables.  These error messages occur on numerous lines in my code, and with numerous types of objects

My object arrays are of type 'CTypedPtrArray', and the objects that they hold are CObjects that I use in my openGL windows.

An example of a line that might cause a crash would be:

myObjectArray->GetAt(7), where this array has a size of 10; thus, accessing slot 7 should NOT create a crash.

There is not once specific line or lines in the code where this crash occurs.  And sometimes a line may cause a crash, and other times it creates no crash.

Any thoughts?
0
clintonJ
Asked:
clintonJ
  • 7
  • 6
  • 2
2 Solutions
 
smidgie82Commented:
When you say you ported this project to "VS 8.0 (.net)", do you mean you've simply imported the VS 6.0 project into VS 8.0 and fixed the errors, but are compiling to native code?  Or have you really converted to using managed code?
0
 
clintonJAuthor Commented:
Yes, I am compiling the "native" code.  No managed code yet.
0
 
smidgie82Commented:
Hrm...  Without seeing the code, this is difficult.  What it suggests to me is that either you broke something while fixing the compile errors to make it work under VS8, or you are using some libraries that have been updated, and the preconditions, postconditions, or usage semantics are different from the VS 6 version.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
smidgie82Commented:
Also, make sure your compile settings are set to generate native code, node set to CLR:mixed or something like that.
0
 
itsmeandnobodyelseCommented:
>>>> Access violation reading location 0xfeeeff26
the 0xfeeeff26 doesn't look like a valid pointer.

Did you set the debugger to break immediately on access violation? You'll do that while debugging in the menu Debug - Exceptions - Win32 exceptions. Select the 'access violation' and check the most upper option which forces the debugger to break immediately instead of breaking after the exception nowhere was handled.

>>> myObjectArray->GetAt(7), where this array has a size of 10;
>>> thus, accessing slot 7 should NOT create a crash
did you check the 'this' pointer as well. If the this pointer was invalid it could crash with all members.

>>>> There is not once specific line or lines in the code where this crash occurs
That is an indication that you are using some uninitialized data (it's ok if it was 0 by accident and crashes otherwise) or that some of the data were corrupted cause you were writing beyond arary boundaries, e. g.

     char szName[20];
     AnyClassObject any;

     ...

 with

      strcpy(szName, "AVeryLongLastNameLongerThan20");

you may overwrite some parts of the any object what can lead to a crash or not.

You also should make sure that any loop on fixed sized arrays was correctly accessed. Better change to std::vector if ever possible (it would crash when indexing out of boundaries).

Regards, Alex



     
0
 
clintonJAuthor Commented:
"No Common Language Runtime Support" is already selected.

I did not previously  have the' immediate break' setting for acces violations set, but have now done so.

So here is the strange behavior that I am finding:

I have loops set up to draw each openGL object in one of several windows. The loops are inside the array classes, and they simply loop through all the objects in the array, using GetSize() as the loop size.  A crash will sometimes occur in the loop where I reference a pointer to one of these objects from the array.  I call the pointer 'ptrToObject'.  When I inspect ptrToObject in the 'Watch' window, when a crash occurs,, the address is a bogus address, like 0xddddddd, and the member variable data is bogus or unavailable.  FAIR ENOUGH.  But what's strange is that when I put a 'this' pointer in the Watch (which references the object array), and point to the same slot in the array that I used for the above mentioned pointer ptrToObject, the address in the watch IS VALID and the member data IS VALID.  This makes no sense to me, and is making the debugging process very difficult.

Here's a sample of one of these for loops:

int i = 0;
while (i < GetSize() )
{
      CNode* ptrToObject = GetAt( i++ );
      
      //crash occurs on this next line
      if ( ptrToObject == NULL ||  ptrToObject->m_uNumber < 0 || ptrToObject->m_uNumber > GetSize())      
            AfxMessageBox("Houston, we have a problem with an invalid node number less than zero, at
            continue;
      }

        ptrToObject->Draw();

}

0
 
smidgie82Commented:
It looks like the problem is actually in the GetAt function.  Your code should work correctly, assuming ptrToObject is initialized correctly (i.e., either NULL or a valid pointer).  0xdddddddd may be an invalid pointer, but != NULL.  Could we see the code for GetAt()?
0
 
clintonJAuthor Commented:
The GetAt() function is part of the TypedPtrArray  class, so there shouldn't be anything fancy going on with that.  Here's the code though, from that class, from afxtempl.h:

// CTypedPtrArray<BASE_CLASS, TYPE>

template<class BASE_CLASS, class TYPE>
class CTypedPtrArray : public BASE_CLASS
{
public:
      // Accessing elements
      TYPE GetAt(INT_PTR nIndex) const
            { return (TYPE)BASE_CLASS::GetAt(nIndex); }

....
....
0
 
clintonJAuthor Commented:
Another example of the object getting inadvertantly trashed is the following drawing routine within the object class.  I've put several test variables in placeIWTHIN A SINGLE drawing function, so I can inspect the value of a certain member variable.  Thus, I can find out immediately when the object gets bad data.

CMyOjbect::Draw()
{
int nTestOne = m_SomeObjectProperty;

//some code

int nTestTwo = m_SomeObjectProperty;

//some code

int nTestThree = m_SomeObjectProperty;

//some code

int nTestFour = m_SomeObjectProperty;

//some code

int nTestFive = m_SomeObjectProperty;

//some code

}

Ideally, the values of nTestOne, nTestTwo, nTestThree, nTestFour and nTestFive should ALWAYS have identical values, because i'm always assigning their value from the same member varible.  However, in my program, a crash sometimes occurs within this drawing function.  When I then inspect the values of my test variables, the test variable closest to the crash (but above the crash line of course) will have bogus data, like -41787322, etc.  However, the other test variables above the bad one will have valid data. In other words, when my object gets inexplicably trashed, a crash will occur.  BUT  I AM CERTAIN that the code itself within this drawing function is IN NO WAY ALTERING THE DATA WITHIN THIS OBJECT.  Nonetheless, the object is getting trashed.







}
0
 
smidgie82Commented:
Is this a multithreaded app?  Behavior like this is common in multithreaded apps where the classes being used aren't thread-safe.  In a single-threaded app, though, what you're describing should NOT happen, assuming all the objects are in thread-local storage and not being accessed by any other processes.

Have you made sure to update your copy of Visual Studio to the latest released version?  Same with the Platform SDK, and any libraries you're using?
0
 
clintonJAuthor Commented:
It is a multithreaded app.  The app I'm working on was written by someone else, and I know very little about multithreading.  I can tell you that the openGL windows in the app use multithreading.  I derive them from my openGL class.  The only code I've found in my openGL classes is in this base class, in two locations:

#1:

BOOL COpenGLWnd::InitOpenGL()
{
      DWORD dwWaitResult;
    dwWaitResult = WaitForSingleObject(
        m_hCreationMutex,   // handle of mutex
        5000L);   // five-second time-out interval
    switch (dwWaitResult)
    {
        case WAIT_OBJECT_0: // The thread got mutex ownership.
            break;
        case WAIT_TIMEOUT: //1 Cannot get mutex ownership due to time-out.
        case WAIT_ABANDONED: //2 Got ownership of the abandoned mutex object.
            break;
    }
....
....

}


and #2:

void COpenGLWnd::DrawSceneProtected()
{
/*
    DWORD dwWaitResult;
    dwWaitResult = WaitForSingleObject(
        m_hCreationMutex,   // handle of mutex
        5000L);   // five-second time-out interval
    switch (dwWaitResult)
    {
        case WAIT_OBJECT_0: // The thread got mutex ownership.
            break;
        case WAIT_TIMEOUT: //1 Cannot get mutex ownership due to time-out.
        case WAIT_ABANDONED: //2 Got ownership of the abandoned mutex object.
            break;
    }
*/
      DrawScene();

//    ReleaseMutex(m_hCreationMutex);

}

Note that in this second function, DrawSceneProtected(), the thread-related code is commented out.  I tried running the app with this uncommented, but experienced similar results, ie, crashing and instability.  So, I'm not really sure which direction to take.  If I comment out all calls to these drawing functions,  the app runs fine, and doesn't crash.

What are some things i can do to make my classes "thread-safe", as you put it?
0
 
clintonJAuthor Commented:
CORRECTION: when I wrote "The only code I've found in my openGL classes is in this base class, in two locations:", i meant to say "The only THREAD-RELATED code I've found in my openGL classes is in this base class, in two locations:"
0
 
itsmeandnobodyelseCommented:
>>>> is a bogus address, like 0xddddddd
0xddddddd is the address  that was set in debug mode to a pointer member where the instance of the class was deleted:

class X
{
     char* psz;
public:
     X() : psz(new char[10]) {}
     ~X() { delete []psz; }
     char* getpsz() { return psz; }
};

   X* px = new X;

   ...

    delete px;   // after that the psz member is 0xdddddddd

I would guess the problem is cause you are storing pointers in the arrays which were deleted somewhere else. If you take such a pointer object from the array all member pointers (and member pointers of class members as well) have the 0xddddddd what leads to the crash.

Note, the 0xdddddddd setting is a really help cause you well know now that the object you are dealing with was a deleted object.
   
0
 
clintonJAuthor Commented:
Thanks guys.  smidgie82, you we're right about it being a multithreaded app.  itsmeandnobodyelse, you were right about the 0xdddddddd indicating a bad pointer.  What I've wound up doing to solve this is put some flags inside a couple functions that delete and recreate certain objects.  Then, in my drawing functions, I check to make sure that the the function that deletes and creates the objects is NOT currently being executed.  This technique is working well for me.
0
 
smidgie82Commented:
Thanks, clintonJ.  If you want to learn more about thread-safe programming, and how to prevent this sort of thing in the future, read up on semaphores, critical sections, mutexes, and re-entrant code (and how to ensure your code is reentrant).  Also, IPC (inter-process communication) practices such as shared memory, messages, sockets, etc. are good to use for thread synchronization, though sometimes too heavy-duty (mutexes and semaphores on shared objects can frequently be used instead).

Good luck on your project, and future endeavors.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 7
  • 6
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now