#1 2016-06-09 15:39:48

CycleSoft
Member
Registered: 2013-01-18
Posts: 34

Problem with TDynArrayHashed.HashAdd

Hi,
just updated to the last and greatest mORMot from git, from a while ago.
A strange behaviour is hitting me. I tracked down the issue to the method

TDynArrayHashed.HashAdd(const Elem; aHashCode: Cardinal; var result: integer);
var n,cap: integer;
begin
  n := Count;
  SetCount(n+1); // reserve space for a void element in array
  cap := Capacity;
  if cap*2-cap shr 3>=fHashsCount then begin
    // fHashs[] is too small -> recreate
    ReHash;
    result := HashFind(aHashCode,Elem); // fHashs[] has changed -> recompute
    assert(result<0);
  end;
  with fHashs[-result-1] do begin // HashFind returned negative index in fHashs[]
    Hash := aHashCode;
    Index := n;
  end;
  result := n;
end;

I do not use this class direclty, it is used by SynDB since I'm connecting to a SQL Server 2008 to access axtrernal data.

in my findings when the statement

n := Count;

sets n to zero, fHashs is not properly allocated, thus resulting in an AV when the statement

  with fHashs[-result-1] do begin // HashFind returned negative index in fHashs[]
    Hash := aHashCode;

executes.

I temporarily solved commenting out the check
  //if cap*2-cap shr 3>=fHashsCount then begin
and thus always executing ReHash;

Of course in this way all your speed optimizations are gone with the problem smile

Verified with XE4/XE7 targeting win32, under Win7 64 bit.

I'm sorry but I was not able to better track the 'root' issue, I suspect this is only a consequance effect of something more deep.

If you need more details I'm here to help.

Offline

#2 2016-06-09 16:12:53

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,660
Website

Re: Problem with TDynArrayHashed.HashAdd

How is Count reset to 0 in your case?
Sound like if fHashCount is > 0 whereas Count = 0 in your case.
I was not able to reproduce it here.
HashAdd() should always be predecessed by a HashFind() call, which set the proper result value.

What is the call stack from SynDB?

Are you using the latest revision of the framework?

Offline

#3 2016-06-09 16:43:19

CycleSoft
Member
Registered: 2013-01-18
Posts: 34

Re: Problem with TDynArrayHashed.HashAdd

Hi ab,

here is the call stack:

SynCommons.TDynArrayHashed.HashAdd((no value),102850746,-1)
SynCommons.TDynArrayHashed.FindHashedForAdding((no value),True,102850746)
SynCommons.TDynArrayHashed.AddAndMakeUniqueName('ID')
SynOleDB.TOleDBStatement.BindColumns(Pointer($3B97368) as IColumnsInfo,$2D4C880,((0, 0, 0, 0, nil, nil, nil, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, nil, nil, nil, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, nil, nil, nil, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, nil, nil, nil, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, nil, nil, nil, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, nil, nil, nil, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, nil, nil, nil, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, nil, nil, nil, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, nil, nil, nil, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, nil, nil, nil, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, nil, nil, nil, 0, 0, 0, 0, 0, 0, 0, 0)))
SynOleDB.TOleDBStatement.FromRowSet(Pointer($3B97360) as IRowset)
SynOleDB.TOleDBStatement.ExecutePrepared
SynDB.TSQLDBConnectionProperties.Execute('SELECT F.ID, F.DESCRIZIONE, F.IDPADRE, F.TITOLOFORM, F.ABILITATO, F.ID_CMTMODULI,PROF.bAbilitaInsert, PROF.bAbilitaEdit, PROF.bAbilitaDelete,MENU.FUNZIONE, MENU.NOME_ICONA FROM CMTFUNZIONI F JOIN SYS_FUNZIONI_HTML5 MENU ON F.ID = MENU.ID_CMTFUNZIONI LEFT OUTER JOIN CMTFUNZIONI PADRE ON F.IDPADRE = PADRE.ID  JOIN CMTMODULI ON F.ID_CMTMODULI = CMTMODULI.ID JOIN CMTEXPROFILIFUNZIONI PROF ON PROF.ID_CMTFUNZIONI = F.ID OR Prof.ID_CMTFUNZIONI=0 JOIN CMTEXUTENTIPROFILI C ON Prof.ID_CMTEXPROFILIUTENTE = C.ID_CMTEXPROFILIUTENTE  JOIN CMTUTENTI U ON C.ID_CMTUTENTI = U.ID WHERE U.ID=? AND ((F.ID_CMTMODULI=? AND F.VISIBILE=''T'') OR ( F.VISIBILE=''F'' AND F.ABILITATO=''F'' AND F.EXE_PARAMS=''HTML5'' )) ORDER BY PADRE.INDICE, F.INDICE',(...),nil,False)
BFiveService.UtenteService.TUtenteService.Profilo($30C5278,$2E214F0,$30D4F10)

The framework is updated at Now()

The statement in my code that originates the problem is something like

        Qry := ConnectionProperties.Execute(SQLText, [User.ID_CMTUTENTI, ModuleID]);

The statement is used in a loop, executed a few times with differents parameter's values

Offline

Board footer

Powered by FluxBB