Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Access violation debugging

Status
Not open for further replies.

350Zed

Programmer
Aug 30, 2007
13
GB
I'm working with Borland C++ Builder 6 on an XP system trying to debug and fix issues with a legacy system. Personally I have 10 years code experience but only 6 months working this intensely with C++ and only 6 months experience of the application I'm trying to fix - joy!

I currently have two issues both being access violation problems.

1) The application will frequently hang with an access violation message. When and where this happens is not consistent and varies from PC to PC so I'm thinking memory leakage. However the application is large so it's something of a needle in a haystack trying to work out where the problems are.

2) I currently have a very repeatable access violation in a small subsection of the code. It is a standalone exe that runs fine. WinMain executes and everything works, then it returns 0 to the OS and I get 3 violation popups in a row. I assume the OS is performing a clean-up on the exe's resources and there is some sort of sharing problem.

So to my questions...
Is there anything I can do with the addresses given in the error popups that would help me find the root of the issues? Also is there any useful info on reading the CPU output of the borland debugger? (I know in theory what it's trying to tell me, I just don't know what it's saying!)

Thanks in advance.
 
Since the program is giving AVs on the exit, I suspect that the problem may be invalid pointers. In re-reading an old tip from the now defunct bytamin-c website, Scott Cross suggested some things to fix this.
1. After declaring the pointer, set it to NULL, If not, you do not new it right away. If the application exits and a delete is performed, the pointers address will be meaningless and you will experience an AV.

2. After deleting a pointer, set it to NULL. Although the delete command actually clears memory, it does not clear the pointer address. If a subsequent delete is performed on that pointer, it will raise an AV.

Remember that there is nothing wrong with deleting a NULL pointer and nothing bad will come from this.

He suggested that by following these two rules, you could eliminate 50% of your AVs. I can't verify that but I know from experience that if you DON'T do the above, you can get AVs. Whenever possible, I create an object in a try...finally clause with the finally section NULLing any pointers I've created.

A couple of other suggestions he gave was to let the owner of an object delete the object and use caFree on your forms.
If you create an object that is owned by another object, let the owner do the deleting. Confuse? Allow me to explain by example. If you create a panel dynamically and in the new statement you pass the owner as a form (Tpanel MyPanel = new Tpanel(this)), then when the owner is deleted, it will attempt to delete your panel. If you have already deleted it, walla, AV. So whenever you new an object and pass an owner in the constructor, instead of deleting it yourself, let Builder do it. If you must delete it, make sure you set it to NULL. . . .

If you can, instead of deleting an instance of a dynamically created form, use caFree in its exit event. Although this may not solve your access violation, the result if you will be able to isolate the cause since the AV will occur on the event instead of on application termination.

I had an app that I wrote with over 3 million lines of code. Every once in a while, I would get an AV when the app closed. It took me 6 months to figure it out. When I closed the app, I was trying to close the database and some serial ports. Turned out that the section of code was never being called. Sometimes the serial ports and DB were being closed in other places but not on the app close section. I moved the calls to the correct close method and the AVs when away.

Hope this helps. Good luck.


James P. Cottingham
-----------------------------------------
[sup]I'm number 1,229!
I'm number 1,229![/sup]
 
Thanks James. Sounds like I've got to roll my sleeves up and start digging!
 
I have fixed problem 2 - more by luck than judgement so I thought I'd post something here to see if anyone can help me understand why it worked. (Or point out that it's just masked the problem!)

Here is the code involved:
First the toplevel entry class of the executable...
Code:
Main class:
//---------------------------------------------------------------------------

#include <vcl.h>

#include "databaselogon.h"
#include "subclass.h"

#pragma hdrstop
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
  TSession *OldSession = Session;
  DataBaseLogOn *logon = new DataBaseLogOn (Application, NULL);
  Session = logon->LogonSession;

  try
  {
    try
    {
      Application->Initialize();
      logon->username = "johndoe";
      logon->password = "password123";
      if(logon->Connect(3))
      {
        SubClass(Application,NULL, logon, true);
      }
    }
    catch (Exception &exception)
    {
       Application->ShowException(&exception);
    }
    catch (...)
    {
       try
       {
         throw Exception("");
       }
       catch (Exception &exception)
       {
         Application->ShowException(&exception);
       }
    }
  }
  __finally
  {
    delete logon;
    logon = NULL;

    Session = OldSession;
  }
  return 0;
}
//---------------------------------------------------------------------------

And now the class it calls...
Code:
Sub class:
//---------------------------------------------------------------------------

#include <vcl.h>
#include <windows.h>
#include "databaselogon.h"
#include "FormForProcessingStuffUnit.h"
#include <dbtables.hpp>
#include "ObjectClass.h"
#pragma hdrstop
//---------------------------------------------------------------------------

#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
  return 1;
}
//---------------------------------------------------------------------------

extern "C" void __declspec(dllexport) SubClass(TApplication* callingApplication,TComponent *owner, DataBaseLogOn* logon, bool mode)
{
  TApplication* oldApplication = Application;
  Application = callingApplication;
[b][COLOR=red]  TDatabase* database = new TDatabase(NULL);
  database->DatabaseName = logon->database->DatabaseName;
  database->Handle = logon->database->Handle;

  TQuery *q = new TQuery(NULL);
  logon->SetQuery(q);
[/color][/b]
  TFormForProcessingStuff *doStuff = new TFormForProcessingStuff(owner,logon,mode);
  doStuff->ShowModal();
  delete doStuff;
  doStuff = NULL;
[b][COLOR=red]
  delete q;
  q = NULL;

  delete database;
  database = NULL;
[/color][/b]
  Application = oldApplication;
}
//---------------------------------------------------------------------------

While checking the code that's been giving me issues I noticed the code highlighted above was not used so deleted it and that has solved the AVs when the exe terminates.

What I don't quite understand is that I have removed code that created two pointers (database, and q), and then deleted and nulled them so why were they giving problems? Is it because they were created but never used, or as I said at the start, have I just masked a different problem?

Thanks again.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top