2015-12-29 91 views
1

sharedMemory的這個限制是實際的嗎? 我已經傳遞給DLL字符串長度在370個字符左右,DLL讀取沒有問題。Delphi DLL PChar

我在問,因爲我從DLL返回PChar到EXE程序。 在DLL中,我使用GetMem()函數,並在EXE程序中使用了FreeMem()函數,並且我使用了構造函數調用導出的函數,並且它可能會崩潰。

當我從Exec中刪除FreeMem時,未顯示此AV。也不總是顯示出來,它取決於PChar變量中的字符:

255 x a - 可以通過 但是可以崩潰。

例子 - 在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; 

和在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; 
+0

是的,實際上,你必須在模塊之間共享堆。 –

+0

我相信,我可以通過shortString,因此爲了返回,我可以使用shortstring並且不分配內存。對於第二個問題 - 我讀了我應該導出用於釋放DLL中的內存的函數--DLL分配內存,並且DLL應該釋放內存。 – InnerWorld

+0

即使你設法做這個工作,這是一個壞主意。我希望你在嘗試這種方式時學習一些有趣的東西,最值得注意的是,你應該創建API並從DLL中導出它們,而不需要主機(exe)和guest(dll)共享兼容的堆實現,或者任何特定類的相同副本或其他二進制「對象」。 –

回答

4

主機可執行文件和DLL具有存儲器管理器的兩個單獨的副本。

要共享這樣的內存您需要使用shared memory manager

作爲一種替代方案,您可以重新設計API,以便只在一側發生分配和釋放,無論是在DLL中(公開一個函數以釋放),還是在主機可執行文件中都發生(公開一個函數以返回所需的緩衝區大小,並讓調用者分配和釋放)。