Jump to content
alogrep

Detect when/what makes a tcomponet descendent is made NIL?

Recommended Posts

Hello everybody. 

Another  one of my misteries :classic_biggrin:.

I have created a component Tslim(TComponent);

It is basically a table with cells and row that are created dynamically.

In a particular procedure that creates new cells and rows, something happens that suddenly the Slim becomes NIL.

That is in a try… except block, when the exception is raised, I inspect the value of Slm, and it shows NIL.

The Slim.Destroy is not triggered.

Is the a way or something (an Event?) that could be triggered the moment this happens  so I can find out what exactly causes that?

Share this post


Link to post

I found where the problem occurs (see apptached image). However the call stack doesn't go inside the procedure where the problem actually happes. This is the code cpu.thumb.jpg.f076502ae88d23f285eb77d40597cd01.jpg

procedure (g:Tslim; html:string);
var
  c,r: integer;
begin
 C:=0; R:=0;
 WITH G DO       // this is the "slim" component
    while (HTML <> '') and (html <> ';') and (copy(html,1,5)<>'slim:') DO BEGIN
try
      N:=POS('<col',html);
      if n>0 then begin
       if c> colcount-1 then
         colcount:=c;
      if alreadytranslated then begin
       if (g=extras) and (c=0) and (r>0) and (copy(html,1,5) <> _nota) then
          cells[c,r]:='    '+copy(html,1,n-1)
       else
         cells[c,r]:=copy(html,1,n-1);

      end else
       if (g=extras) and (c=0) and (r>0) and (copy(html,1,5) <> _nota) then
          cells[c,r]:='    '+Fromspanish(copy(html,1,n-1))
       else
         cells[c,r]:=FromSpanish(copy(html,1,n-1));
        system.delete(html,1,n+3);
       if (g=extragrid)  and (c=0) then begin
         k:=pos('line-through',html);
         if (k>0) then begin
           orderline.disabledrows[r]:=true;
           system.delete(html,k,12);
         end;
       end;
       n:=pos('color:::',html);
       if (n=1) then begin
         if  (copy(html,9,4) <> 'null')then begin
           if copy(html,9,1) ='#' then begin
             cellcolors[c,r]:=HexcolToTcolor(copy(html,10,6));
             system.delete(html,1,15);
           end else begin
             cellcolors[c,r]:=HexcolToTcolor(copy(html,9,6));
             system.delete(html,1,14);
           end;
         end else
           system.delete(html,n,12);
       end;
       k:=pos('<row',html);
       if k=1 then begin
         system.delete(html,1,k+3);
         c:=-1; // inc() below to 0
         inc(r);
         if r> rowcount-1 then
           rowcount:=rowcount+1;
         kount:=rowcount;
       end;
       inc(c);
     end else
      break;
EXCEPT
  showmessage(inttostr(c)+' '+inttostr(r)+'  '+sparam);
 END;
end;
end;

 

Share this post


Link to post

my first tip: avoid "WITH" usage, always that possible!

  • it's messy and leads to basic error induction, even though everything looks ok in the build!

if "G" it's your component, then, maybe you should look before this line... what happens before this line? "With G do..."

  • because, when "G" ...ColCount.../ Cells[...] / ...CellColors[...] etc... --> if "G" is nil, then you catch a "AV".
Edited by programmerdelphi2k

Share this post


Link to post

 

17 minutes ago, alogrep said:

However the call stack doesn't go inside the procedure where the problem actually happes.

Then the problem is not actually happening inside that procedure (though the root cause may be there). The problem is occurring in a method in the Http unit, in a class called TTCPHttpThrd in a method with a name starting with "ProcessH", but the rest of the callstack window is cut off in your screenshot

Share this post


Link to post
4 hours ago, alogrep said:

I found where the problem occurs (see apptached image). However the call stack doesn't go inside the procedure where the problem actually happes. This is the code

There is a thread involved. Most likely not all data that needs to be protected is protected and another thread is either releasing the object while it is still in use, or there is memory corruption because multiple threads are messing with the data.

 

But there is not enough code to pinpoint the problem. 

Share this post


Link to post

What I don’t understand is: how come the G variable is set to NIL? From what I have seen if an object is destroyed for say AV, it is destroyed but not set to NIL.

A to send more code, it is not feasible because is too long and nobody would take the time or have the patience to read it.

I can give the “scheme” I use..

  type
     tgrids=record
       g1,hgrid,tabgrid,extras,extragrid,groupqty,servgrid,all,mitad1,mitad2:Tslim;
     end;

  type OrderLinevars = record
    grids: Tgrids;
    myCompname_,pass, curtabtrans:string
    // and a bunch of other variables;
  end;
  type
   orderlinerec = record
    id: string;
    orderline: OrderLinevars;
  end;

  type
    orderlinearr= array of orderlinerec;
    PtRecord=^OrderLinevars;

  in main form I have this
    public
     orderlines : orderlinearr;


  TTCPHttpThrd = class(TThread)
  private
    Sock:TTCPBlockSocket;
    orderline: PTREcord;
    thisip,objs: string;
    .........

When there is a new POST request, a new thread is created and executed/

  in the Execute part, as the first thing, I do

 

       FOR N:=0 TO HIGH(MAIN.ORDERLINES) do
           if (MAIN.orderlines[n].id=thisip)
           then begin
             orderline:=@MAIN.orderlines[n].orderline;
             orderlineindex:=n;
             break;
           end;
        if orderlineindex<0 then  begin
          setlength(main.orderlines,length(main.orderlines)+1);
          orderlineindex:=high(main.orderlines);
          MAIN.orderlines[orderlineindex].id:=thisip;
          orderline:=@MAIN.orderlines[orderlineindex].orderline;
        end;

  The "orderline" is used (for brevity) in all calculations inside the execute.

     I need some variables that are part of the orderlinerec ->  OrderLinevars to be persistent;

     All the grids are set to NIL at the beginning of Execute, freed at the end;

     For example, a POST requests set some variables that I need to re-use later for another POST request from the same user.

Just as lost as before.

Share this post


Link to post
1 hour ago, alogrep said:

A to send more code, it is not feasible because is too long and nobody would take the time or have the patience to read it.

You could at least post the code for whatever the method is that starts with "ProcessH", as per my earlier comment. You provided a screenshot and said that is where the problem occurs.

 

Share this post


Link to post

What is main? 

 

You are most likely corrupting a memory by accessing same data from main thread and background thread. Also you shouldn't work with any visual control from the background thread without calling the TThread.Synchronize or TThread.Queue

Also you are working with pointers, so it is possible that you are accidentally overwriting something.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×