AV in BookmarkValid

Discussion of open issues, suggestions and bugs regarding SDAC (SQL Server Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
Post Reply
colek
Posts: 3
Joined: Wed 10 Apr 2013 05:54

AV in BookmarkValid

Post by colek » Thu 11 Apr 2013 05:51

Hello,

I have problem with TMSQuery.BookmarkValid method - Access violation.
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.

AndreyZ

Re: AV in BookmarkValid

Post by AndreyZ » Thu 11 Apr 2013 12:33

Hello,

Thank you for the information. We have fixed this problem. This fix will be included in the next SDAC build.

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

Re: AV in BookmarkValid

Post by Romano » Fri 26 Apr 2013 08:07

Hi,
is it some date of release of new build? We need this patch very much...

Thanks
Roman Krupicka

AndreyZ

Re: AV in BookmarkValid

Post by AndreyZ » Sat 27 Apr 2013 10:09

SDAC version 6.7.13 with the fix is already available. You can download it from Registered Users' Area.

Post Reply