Problem with bookmarks in version 5.10.0.6

Discussion of open issues, suggestions and bugs regarding SDAC (SQL Server Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
Post Reply
Romano
Posts: 41
Joined: Tue 10 Feb 2009 11:21

Problem with bookmarks in version 5.10.0.6

Post by Romano » Wed 18 May 2011 06:38

Hi,
we changed SDAC version in our application from 5.0.0.3 to 5.10.0.6.
And we have problems with bookmarks now. Several customers reported Access Violation Error. EurekaLog shows the same place - unit MemData, row 7019 (function TMemData.BookmarkValid(Bookmark: PRecBookmark): boolean;). We recompiled our application with older version of SDAC (5.0.0.3) without any other changes in our sources and customers reported that all is OK. So it looks that problem is in SDAC...
We cannot simulate this behavior. It happens sometimes but regularly (but not in our lab, we cannot debug it)...

Regards
Roman Krupicka

AndreyZ

Post by AndreyZ » Wed 18 May 2011 11:02

Hello,

Do you have SDAC with source code? If yes, please check that you compile your project without the "Complete boolean eval" compiler option. You can check it in your project options (Project->Options in the Delphi main menu) at the Compiler tabsheet.

Romano
Posts: 41
Joined: Tue 10 Feb 2009 11:21

Post by Romano » Wed 18 May 2011 13:28

Hi,
we compile with $B-.

AndreyZ

Post by AndreyZ » Thu 19 May 2011 07:26

I cannot reproduce the problem. Please try composing a small sample to demonstrate the problem and send it to andreyz*devart*com, including a script to create and fill a table. Also please specify the exact version of your IDE.

Romano
Posts: 41
Joined: Tue 10 Feb 2009 11:21

Post by Romano » Thu 19 May 2011 11:02

Hi,
sorry, but I cannot reproduce the problem either. I know one thing only - version 5.0.0.3 works, version 5.10.0.6 sometimes generates error.

5.0.0.3
if IntPtr(Bookmark) nil then
Result := (Bookmark.Order -1) or (IntPtr(Bookmark.Item) nil)
else
Result := False;

5.10.0.6
if IntPtr(Bookmark) nil then
Result := ((Bookmark.Order -1) and (Bookmark.Order nil) and (Bookmark.Item.Order nil, but it is not valid pointer, so Bookmark.Item.Order generates error...? Maybe somewhere in your code Bookmark.Item is freed but not niled... I don't know.

Sorry, I don't have any other information. Only different version of SDAC.

Regards
Roman Krupicka

AndreyZ

Post by AndreyZ » Thu 19 May 2011 13:22

Please check if you call the FreeBookmark method in your application. For example, the following code will lead to access violation error:

Code: Select all

bm := MSQuery.GetBookmark;
MSQuery.FreeBookmark(bm);
if MSQuery.BookmarkValid(bm) then // here an access violation error will arise
  MSQuery.GotoBookmark(bm);
You cannot use bookmark after its freeing.

colek
Posts: 3
Joined: Wed 10 Apr 2013 05:54

Re: Problem with bookmarks in version 5.10.0.6

Post by colek » Wed 10 Apr 2013 06:51

Hello,

I have the same problem with TMSQuery.BookmarkValid method.
I use SDAC 6.6.12 with source code under Windows 7 and Delphi XE.

I prepared test project for AV demonstration. It contains these files:
  • Project1.dpr
    Unit1.pas
    Unit1.dfm
    MemMgr.pas
Just click on Button2.

Regards
Martin Kolek


Project1.dpr

Code: Select all

program Project1;
uses
  MemMgr in 'MemMgr.pas',
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
Unit1.pas

Code: Select all

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, DB, MemDS, DBAccess, MSAccess;

type
  TForm1 = class(TForm)
    Connection: TMSConnection;
    Query: TMSQuery;
    Button2: TButton;
    Label3: TLabel;
    lPocet2: TLabel;
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses
  MemData;

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);

  function __GetQueryStr(PocetZaznamu: integer): string;

    function __RandomChar: string;
    begin
      Result := Chr(65 + Random(26));
    end;

    function __RandomWord(PocetPismen: integer): string;
    var
      i: integer;
    begin
      Result := '';
      for i := 0 to PocetPismen - 1 do
        Result := Result + __RandomChar;
    end;

  var
    i: integer;
  begin
    Randomize;
    Result := 'SELECT * FROM (';
    for i := 0 to PocetZaznamu - 1 do
    begin
      if i = 0 then
        Result := Result +
          Format(
            '(SELECT %d AS Field1, ''%s'' AS Field2, ''%s'' AS Field3, ''%s'' AS Field4)',
            [Random(1000),
             __RandomWord(3),
             __RandomWord(2),
             __RandomWord(1)])
      else
        Result := Result +
          Format(
            '(SELECT %d, ''%s'', ''%s'', ''%s'')',
            [Random(1000),
             __RandomWord(3),
             __RandomWord(2),
             __RandomWord(1)]);
      if i < (PocetZaznamu - 1) then
        Result := Result + ' UNION ALL'#13
    end;
    Result := Result + ') t';
  end;

var
  i: integer;
  S: string;
  B: TBookmark;
begin
  for i := 1 to 100 do
  begin
    Connection.Connect;

    Query.SQL.Text := __GetQueryStr(200);
    Query.Open;

    Query.Last;
    B := Query.Bookmark;

    Query.Close;
    Query.SQL.Text := __GetQueryStr(50);
    Query.Open;

    if not Query.BookmarkValid(B) then ; // AV here. Bookmark.Item is the dangling pointer

    lPocet2.Caption := IntToStr(StrToIntDef(lPocet2.Caption, 0) + 1);
    lPocet2.Refresh;
  end;
end;
end.
Unit1.dfm

Code: Select all

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 335
  ClientWidth = 396
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Label3: TLabel
    Left = 80
    Top = 150
    Width = 107
    Height = 13
    Caption = 'AV with BookmarkValid'
  end
  object lPocet2: TLabel
    Left = 85
    Top = 75
    Width = 6
    Height = 13
    Caption = '0'
  end
  object Button2: TButton
    Left = 80
    Top = 170
    Width = 211
    Height = 71
    Caption = 'Button2'
    TabOrder = 0
    OnClick = Button2Click
  end
  object Connection: TMSConnection
    Authentication = auWindows
    Left = 25
    Top = 20
  end
  object Query: TMSQuery
    Connection = Connection
    Left = 60
    Top = 20
  end
end
MemMgr.pas

Code: Select all

unit MemMgr;

interface

implementation

uses
  Windows;

{ Memory Management }

const
  HEAP_MAX_SIZE = $100000;
  HEAP_GENERATE_EXCEPTIONS = $00000004;
  HEAP_NO_SERIALIZE = $00000001;
  HEAP_ZERO_MEMORY = $00000008;

var
  PrivateHeap: THandle;
  SavedMemoryManager: TMemoryManager;

function InternalGetMem(Size: Integer): Pointer;
begin
  Result := HeapAlloc(PrivateHeap, HEAP_GENERATE_EXCEPTIONS or HEAP_NO_SERIALIZE or HEAP_ZERO_MEMORY, Size);
end;

function InternalFreeMem(P: Pointer): Integer;
begin
  Result := Integer(not HeapFree(PrivateHeap, HEAP_NO_SERIALIZE, P))
end;

function InternalReallocMem(P: Pointer; Size: Integer): Pointer;
begin
  Result := HeapReAlloc(PrivateHeap, HEAP_GENERATE_EXCEPTIONS or HEAP_NO_SERIALIZE or HEAP_ZERO_MEMORY, P, Size)
end;

const
  MemoryManager: TMemoryManager = (
    GetMem: InternalGetMem;
    FreeMem: InternalFreeMem;
    ReallocMem: InternalReallocMem
  );

initialization
  PrivateHeap := HeapCreate(HEAP_GENERATE_EXCEPTIONS or HEAP_NO_SERIALIZE, 0, HEAP_MAX_SIZE);
  GetMemoryManager(SavedMemoryManager);
  SetMemoryManager(MemoryManager);

finalization
  HeapDestroy(PrivateHeap);
  SetMemoryManager(SavedMemoryManager);
end.


Post Reply