2010-11-24 7 views
8

पर रिटर्न पैचर आवंटित करना होगा मेरे पास एक डीएलएल है जिसमें मेरे पास एक फ़ंक्शन है जो एक पचर देता है। मैं मूल रूप से क्या कर रही एक pchar के रूप में एक स्ट्रिंग कास्टिंग किया गया था और लौटने किमेरे डीएलएल में डेल्फी में मुझे एक फ़ंक्शन

Result := pChar(SomeFuncThatReturnsString) 

लेकिन मैं उम्मीद मिल रही थी, परिणाम समय के 90% और अन्य समय मैं वापस मिलेगा था (borlndmm उपयोग करने के लिए होने से बचाने के रूप में) कुछ भी तो नहीं।

मुझे तब यह सोचने लगा कि मुझे पचर के लिए स्मृति आवंटित करने की आवश्यकता है और यह करने के लिए मुझे अपना मूल तरीका स्मृति में एक पचर पॉइंट था जो हमेशा मूल रूप से कहा जाता था जब वहां होता था। इसलिए मैं अब इस

Result := StrAlloc(128); 
Strcopy(Result,PAnsiChar(Hash(Hash(Code,1,128),2,128))); 

है लेकिन यह मुझे कार्यक्रमों अंत जो मैं

StrDispose(Pstr);  

के साथ क्या पर आबंटित स्मृति को साफ करने के होने के साथ छोड़ देता है तो $ 64 सवाल है: मैं आवंटित करने के लिए है एक डीएलएल के अंदर एक समारोह से एक पीसीहर लौटने पर स्मृति या क्या मैं इसे एक पीसीहर में डाल सकता हूं?

उत्तर

7

इस मुद्दे के लिए सामान्य दृष्टिकोण यह है कि ऐप मेमोरी आवंटित करे और फिर इसे भरने के लिए डीएलएल को पास कर दें (इससे भी बेहतर अगर डीएलएल ऐप को यह पूछने की अनुमति देता है कि उसे कितनी मेमोरी आवंटित करने की आवश्यकता है, तो यह नहीं है ज्यादा आवंटित स्मृति) के लिए है:

function GetAString(Buffer: PChar; BufLen: Integer): Integer; stdcall; 
var 
    S: String; 
begin 
    S := SomeFuncThatReturnsString; 
    Result := Min(BufLen, Length(S)); 
    if (Buffer <> nil) and (Result > 0) then 
    Move(S[1], Buffer^, Result * SizeOf(Char)); 
end; 

यह तय करने के लिए कब और कैसे स्मृति को आबंटित करने के लिए एप्लिकेशन की अनुमति देता है (ढेर बनाम ढेर, स्मृति ब्लॉक, आदि) पुन: उपयोग:

var 
    S: String; 
begin 
    SetLength(S, 256); 
    SetLength(S, GetAString(PChar(S), 256)); 
    ... 
end; 

var 
    S: String; 
begin 
    SetLength(S, GetAString(nil, 0)); 
    if Length(S) > 0 then GetAString(PChar(S), Length(S)); 
    ... 
end; 

var 
    S: array[0..255] of Char; 
    Len: Integer; 
begin 
    Len := GetAString(S, 256); 
    ... 
end; 

इस है आपके लिए कोई विकल्प नहीं है, तो आपको डीएलएल मेमोरी आवंटित करने की आवश्यकता है, वापसी करें उपयोग के लिए अनुप्रयोग के लिए यह, और फिर DLL एक अतिरिक्त समारोह एप्लिकेशन जब यह सूचक DLL करने के लिए वापस पारित करने के लिए किया जाता है कॉल कर सकते हैं कि मुक्त कराने के लिए निर्यात कर सकते हैं:

function GetAString: PChar; stdcall; 
var 
    S: String; 
begin 
    S := SomeFuncThatReturnsString; 
    if S <> '' then 
    begin 
    Result := StrAlloc(Length(S)+1); 
    StrPCopy(Result, S); 
    end else 
    Result := nil; 
end; 

procedure FreeAString(AStr: PChar); stdcall; 
begin 
    StrDispose(AStr); 
end; 

var 
    S: PChar; 
begin 
    S := GetAString; 
    if S <> nil then 
    try 
    ... 
    finally 
    FreeAString(S); 
    end; 
end; 
+0

शट डाउन फ़ंक्शन का खुलासा करना इतना है कि विंडोज 3.1 बस डेलमेन में सभी क्लीनअप का करें जब fdwReason = DLL_PROCESS_DETACH –

+0

मेरे उत्तर के साथ इसका क्या संबंध है?इसके अलावा, DllMain() में क्लीनअप हमेशा संभव नहीं होता है, कुछ ऐसे ऑपरेशन होते हैं जिन्हें सुरक्षित रूप से DllMain() के अंदर सुरक्षित रूप से निष्पादित नहीं किया जा सकता है। –

+0

"लाइब्रेरी अनलोड होने से पहले WEP (विंडोज निकास प्रक्रिया) कॉलबैक फ़ंक्शन गतिशील-लिंक लाइब्रेरी (डीएलएल) के लिए क्लीनअप करता है।" क्या आपने यह सुझाव दिया है? पुन: असुरक्षित संचालन - उदाहरण देने के लिए देखभाल? –

5

डीएलएल और आपके मुख्य ऐप में दो अलग-अलग मेमोरी मैनेजर हैं, इसलिए डीएलएल में मेमोरी आवंटित करना गलत है लेकिन इसे मुख्य ऐप में और इसके विपरीत।

आप डेल से स्ट्रिंग लौटने या इसे डीएल में पास करने के लिए वाइडस्ट्रिंग प्रकार का उपयोग कर सकते हैं - वाइडस्ट्रिंग सिस्टम बीएसटी प्रकार के चारों ओर एक रैपर है और वाइडस्ट्रिंग चर के लिए मेमोरी सिस्टम मेमोरी मैनेजर द्वारा स्वचालित रूप से आवंटित की जाती है।

एक और समाधान ShareMem (डेल्फी 2007 और केवल पुराने) के बजाय SimpleShareMem का उपयोग करना है - यह ShareMem की तरह काम करता है लेकिन किसी भी borlnmm.dll-like पुस्तकालयों को पुनर्वितरण करने की आवश्यकता नहीं है।

+1

इस एक, है ना? http://edn.embarcadero.com/article/33416 –

+0

हां, "ShareMemoryManager" अनुभाग। और, मेरी गलती, नया मेमोरी मैनेजर डेल्फी 2006 से शुरू होता है, 2007 से नहीं। –

1

जब आप PChar के रूप में एक स्ट्रिंग लौटाने फ़ंक्शन से स्ट्रिंग स्टैक में आयोजित की जाती है, यही कारण है कि यह कभी-कभी दूषित हो जाता है। मैं स्ट्रिंग्स लौटने के लिए प्रक्रिया ढेर मेमोरी का उपयोग करता हूं, या चार्ट के ग्लोबल बफर सरणी में पॉइंटर का उपयोग करता हूं।

इसके अलावा, आप में निर्मित कोडांतरक का उपयोग करें और यह कर सकते हैं:

Function GetNameStr : PChar; 
Asm 
    Call @OverText 
    DB  'Some text',0 
@OverText: 
    Pop EAX 
End; 
संबंधित मुद्दे