Search code examples
delphimemory-managementdllpchar

Delphi DLL PChar


This limitation for sharedMemory is actual ? I have passed to DLL string length around 370 chars and DLL read it without problem.

I am asking, because I return PChar from DLL to EXE program. In DLL I use GetMem() function, and in EXE program I used FreeMem() function, and

I can get Acces Violation for writing - I call exported function, where I use constructor, and it can crash.

When I remove FreeMem from Exec, This AV is not showed. Also not always it is showed, it depend on characters in PChar variable:

255 x a - can pass but ąłćłąłłąłść łąśććłłć :// can crash.

example - create message in DLL:

function TPDF.wiadomosciBledow(kod: kodyBledow): TWynik;
var
  tmp: string;

begin

  case kod of
    kbOK: tmp := ''; //natomiast tutaj tego nie zauważyłem
    kbBladLogowania: tmp := 'Nie można zalogować się do serwera Archiwum';
    kbBrakAdresSerwera: tmp := 'Wprowadź adres serwera, np.: http://arch.lpwik:5984/';
    kbBrakDanychJSON: tmp := 'Wprowadź dane do logowania w formacie JSON - API _session';
    kbBladPobrania: tmp := 'Nie można pobrać wskazanego pliku';
    kbBrakURL: tmp := 'Wprowadź adres URL do pobrania, np.: http://arch.lpwik:5984/baza/dok_1/zal_1.pdf';
    kbBrakProtokolu: tmp := 'Wymagane jest wprowadzenie protokołu http:// lub https://'; //z jakiegoś powodu wprowadzenie tutaj dwóch slashy // powoduje błąd
  end;

  result.kod := ord(kod);
  GetMem(result.wiadomosc, sizeof(WideChar) * Length(tmp) + 1);
  result.wiadomosc := StrPCopy(result.wiadomosc, tmp);
end;

and in Exec freemem:

procedure TOkno.pokazPDFClick(Sender: TObject);
var
  wejscie: TZalacznik;
  wyjscie: TWynik;
  t: string;

begin
  if @wyswietlPDF = nil then exit();

  {inicjalizacja pamięci - widechar na jeden znak potrzebuje 2 bajty}
  GetMem(wejscie.pelnyAdresURL, 2 * Length(adresURL.Text) + 1);

  {przekopiowanie danych}
  StrPCopy(wejscie.pelnyAdresURL, adresURL.Text);

  {wywołanie metody z DLL}
  wyjscie := wyswietlPDF(wejscie); //dll function

  {wyświetlenie wyniku w grupie}
  wynikKod.Caption := IntToStr(wyjscie.kod);
  wynikWiadomosc.Caption := wyjscie.wiadomosc;

  {zwalnianie przydzielanej pamięci}
  FreeMem(wejscie.pelnyAdresURL);

  FreeMem(wyjscie.wiadomosc); //if commented I do not have AV
end;

Solution

  • The host executable and the DLL have two separate copies of the memory manager.

    To share memory like this you need to use the shared memory manager.

    As an alternative, you could redesign the API so that both allocation and deallocation happen on one side only, either both in the DLL (expose a function to deallocate), or both in the host executable (expose a function to return required buffer size, and let the caller allocate and deallocate).