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 strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Access Violation in trees...

Status
Not open for further replies.

tjc240e

Technical User
Nov 12, 2004
133
US
I am getting an access violation on the last addchildobject i add to my tree? any ideas?

It generates the tree fine just when i go to the form and click on the one that is added last do i get the access violation.

The following code generates the tree:
Code:
[b]procedure[/b] MakeTheTree(udfName, xName:String; xInt: integer);
[b]var[/b]
  xAttdType, xCHAct, TblID: [b]string[/b];
  CSREFTBL: TCBTable;
  DataPtr: PData;
  xEvtType: TEventTypes;
  xAttdTypeCh, udfNameCh: [b]String[/b];
[b]begin[/b]
  [b]with[/b] AttendanceOptionsFrm [b]do[/b]
  [b]begin[/b]
    CSREFTBL.Open;
    CSREFTBL.GoTop;
    [b]IF[/b] xName=[teal]'ALL'[/teal] [b]then[/b] [b]begin[/b]
      CSREFTBL.SetFilter([teal]'TBL_NAME="ALL"'[/teal]);
      xAttdType:=[teal]'ALL'[/teal];
      xEvtType:=ALL;
      [b]end[/b];
    [b]IF[/b] xName=[teal]'CHACTIVITY'[/teal] [b]then[/b] [b]begin[/b]
      CSREFTBL.SetFilter([teal]'TBL_NAME="CHACTIVITY"'[/teal]);
      xAttdType:=[teal]'CA'[/teal];
      xEvtType:=ChurchActivities;
      [b]end[/b];
    [b]IF[/b] xName=[teal]'SUNDAYSCHL'[/teal] [b]then[/b] [b]begin[/b]
      CSREFTBL.SetFilter([teal]'TBL_NAME="SUNDAYSCHL"'[/teal]);
      xAttdType:=[teal]'SS'[/teal];
      xEvtType:=SundaySchool;
      [b]end[/b];
    [b]IF[/b] xName=[teal]'WORSHIP'[/teal] [b]then[/b] [b]begin[/b]
      CSREFTBL.SetFilter([teal]'TBL_NAME="WORSHIP"'[/teal]);
      xAttdType:=[teal]'WS'[/teal];
      xEvtType:=WorshipService;
      [b]end[/b];
    NEW(DataPtr);
    DataPtr^.PID:=udfName;
    DataPtr^.Att_Type:=xAttdType;
    DataPtr^.UDF_Name:=udfName;
    DataPtr^.Event_Tpe:=xEvtType;
    DataPtr^.PosNum:= xInt;
    SelectedNode:=AttList.Items.AddObject(nil, udfName, DataPtr);
    [b]IF[/b] xName<>[teal]'ALL'[/teal] [b]then[/b] [b]BEGIN[/b]
      [b]WHILE[/b] [b]not[/b] CSREFTBL.Eof [b]do[/b] [b]Begin[/b]
        xCHAct :=CSREFTBL.FieldAsString([teal]'TBL_NAME'[/teal]);
        [b]if[/b] CSREFTBL.FieldAsString([teal]'TBL_NAME'[/teal])=xName [b]then[/b] [b]BEGIN[/b]
          xCHAct := CSREFTBL.FieldAsString([teal]'DESC'[/teal]);
          TblID:=CSREFTBL.FieldAsString([teal]'TBL_ID'[/teal]);
          xAttdTypeCh:=[teal]'Attend->'[/teal]+xAttdType+TblID;
          udfNameCh:=udfName+[teal]' - '[/teal]+xCHAct;
          NEW(DataPtr);
          DataPtr^.PID:=TblID;
          DataPtr^.Att_Type:=xAttdTypeCh;
          DataPtr^.UDF_Name:=udfNameCh;
          DataPtr^.Event_Tpe:=xEvtType;
          DataPtr^.PosNum:= xInt;
          AttList.Items.AddChildObject(SelectedNode, xCHAct, DataPtr);
        [b]END[/b];
        CSREFTBL.Skip([purple]1[/purple]);
      [b]END[/b];
      Dispose(DataPtr);
    [b]ENd[/b];
    CSREFTBL.Close;
  [b]end[/b];
[b]end[/b];
 
Apparently either Dispose(DataPtr); is in the wrong location or something is wrong with it. I commented it out and I no longer get the access violations.

When/Where should I be using the Dispose?

I "believe" that the problem is that dispose is destroying the dataptr informatin on the last record.

Any Suggestions would be greatly appreciated.
 
it would be. Do some reading up on pointers and memory allocation if you like, it may make things a bit clearer. But to give you a quick primer:

A pointer is a variable that contains the address of a single memory location. eg.
Code:
[b]type[/b]
  PData = ^TData
  TData = [b]record[/b]
    elem1 : [b]String[/b];
    elem2 : Word;
  [b]end[/b];
PData is a pointer to a TData record. When you declare an instance of PData:
Code:
[b]var[/b]
  DataPtr : PData;
you're only creating a pointer. To create the actual data structure (and the memory it requires for it's elements), you use
Code:
New(DataPtr);
Which reserves memory for the TData record, and sets DataPtr to refer to it.

When you pass DataPtr to other functions
Code:
SelectedNode := AttList.Items.AddObject([b]nil[/b], udfName, DataPtr);
you're only coping the pointer, not the memory being used by the TData record. So if that function modifies the value of DataPtr^ then your original DataPtr^ reference will also change (and any other pointer^ reference to it too), because any such pointer refers to the same memory block.

When you Dispose(DataPtr), you invalidate every pointer in existence that refers to that memory and trying to access the TData record via one of these pointers will cause an access violation because that memory is no longer owned by your program.

So the rule is, Dispose of memory only after your program no longer needs it, which would probably be while the form containing the Attlist control is being destroyed.

 
tjc240e,

if I were you, I would modify the record into an object.

like

Code:
TData = class(Tobject)
    elem1 : String;
    elem2 : Word;
  end;

// at form creation create an objectlist

uses contnrs,...
...
MyObjects:=TObjectList(True);

// destroy objectlist at form destruction, this will also
// destroy all the objects associated with the list
FreeAndNil(MyObjects);


//now when you create a new object, add it to the objectlist

Data:=TData.Create;
MyObjects.Add(Data); // now you don't have to worry about object destruction, the objectlist will take care of this
// do something with data...

My 2 cents...

//daddy





-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top