Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Access violation in System._DynArrayClear (https://www.delphipraxis.net/205456-access-violation-system-_dynarrayclear.html)

Andre1 11. Sep 2020 13:48

Delphi-Version: 10.2 Tokyo

Access violation in System._DynArrayClear
 
Hi,

ich rufe aus einer Bibliothek eine Funktion auf. Diese gibt mir
die Adresse zu einem String Array und die Anzahl der Einträge.
Showmessage funktioniert und mir werden die Strings angezeigt.
Allerdings kommt es beim Verlassen der Funktion getRecipients
zu einer Access Violation hier:

System.SysFreeMem(Opt.out
System._FreeMem(???)
System._DynArrayClear(nil, ???)

Ich vermute es hängt mit der Variable "arr" zusammen.
Was muss ich machen, damit keine Access Violation kommt?

Viele Grüße
André

Delphi-Quellcode:
type
  TPWideCharArray = array of PWideChar;
  PPWideChar = ^PWideChar;
  PPPWideChar = ^PPWideChar;
  PNativeInt = ^NativeInt;
  PPNativeInt = ^PNativeInt;

procedure db_call_method_RecipientsManager_getRecipients(ptr: NativeInt;
  argv: PPPWideChar; argc: PPNativeInt); stdcall; external 'sample.dll';
 
function RecipientsManager.getRecipients: TArray<String>;
var
  argv: PPWideChar;
  argc: PNativeInt;
  i: NativeInt;
  str: string;
  arr: TPWideCharArray;
begin
  db_call_method_RecipientsManager_getRecipients(nativeRef, @argv, @argc);

  Result := Tarray<string>.create();
  SetLength(result, argc^);
  arr := TPWideCharArray(argv);

  for i := 0 to argc^ - 1 do
  begin
    str := WideCharToString(arr[i]);
    result[i] := str;
    Showmessage(str);
  end;
end;

Stevie 11. Sep 2020 17:33

AW: Access violation in System._DynArrayClear
 
Ich tipp mal auf verschiedene Speichermanager, einer in deiner Anwendung und einer in deiner dll. Nutzt du sharemem, runtime packages oder andere Mechanismen um das zu vermeiden?
Mein zweiter Tip nach einem zweiten Blick ist, dass dein Hardcast von argv auf ein array of PWideChar einfach falsch ist.

himitsu 11. Sep 2020 18:13

AW: Access violation in System._DynArrayClear
 
Ich tippte auf den kranken Cast.
Delphi-Quellcode:
arr := TPWideCharArray(argv);


Außerdem werden im Result nur viele PChars aus ein- und derselben Variable verlinkt,
die am Ende auch noch freigegeben wird und somit die PChars alle ungültig sind.

Andre1 11. Sep 2020 18:46

AW: Access violation in System._DynArrayClear
 
Zitat:

Zitat von Stevie (Beitrag 1473435)
Ich tipp mal auf verschiedene Speichermanager, einer in deiner Anwendung und einer in deiner dll. Nutzt du sharemem, runtime packages oder andere Mechanismen um das zu vermeiden?
Mein zweiter Tip nach einem zweiten Blick ist, dass dein Hardcast von argv auf ein array of PWideChar einfach falsch ist.

Die dll ist in der Sprache D geschrieben, diese hat einen GC. Allerdings ist der GC deterministisch (GC collect läuft nur wenn neuer Speicher angefordert wird). Der nächste GC collect wird frühestens im nächsten Aufruf der Dll passieren.

Unterschiedliche Speicherverwaltungen sollten deswegen kein Problem sein.

Viele Grüße
Andre

Andre1 11. Sep 2020 18:56

AW: Access violation in System._DynArrayClear
 
Zitat:

Zitat von himitsu (Beitrag 1473437)
Ich tippte auf den kranken Cast.
Delphi-Quellcode:
arr := TPWideCharArray(argv);


Außerdem werden im Result nur viele PChars aus ein- und derselben Variable verlinkt,
die am Ende auch noch freigegeben wird und somit die PChars alle ungültig sind.

Ja, ich habe versucht es irgendwie zum Laufen zu kriegen mit Code Schnippseln die ich im Internet dazu gefunden habe.

Tatsächlich ist die array cast Zeile, diejenige, welche die access violation auslöst. Wenn ich sie weglassen (und das nachfolgende coding) kommt keine access violation.

Seltsam ist, dass showmessage aber perfekt funktioniert. Sie wird 2 mal gerufen und zeigt jeweils den richtigen String an.

Wie ist der richtige Weg, wenn ich über eine C function eine Liste von Strings bekomme (argv: PPPWideChar; argc: PPNativeInt) und diese in einem Result vom Type TArray<String> zurück geben möchte?

Viele Grüße
Andre

Andre1 11. Sep 2020 20:05

AW: Access violation in System._DynArrayClear
 
Danke für die Antworten.
Ich vermute ich habe die Lösung gefunden:

Delphi-Quellcode:
function RecipientsManager.getRecipients: TArray<String>;
var
  argv: PPWideChar;
  argc: PNativeInt;
  i: NativeInt;
begin
  db_call_method_RecipientsManager_getRecipients(nativeRef, @argv, @argc);

  result := TArray<string>.Create();
  SetLength(result, argc^);

  for i := 0 to argc^ - 1 do
  begin
    result[i] := WideCharToString(argv^);
    if i <> argc^ - 1 then
      Inc(argv, 1);
  end;
end;
Viele Grüße
André


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:07 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz