2010-06-24 10 views
6

यह बिल्कुल एक सीधा सवाल नहीं है क्योंकि मैंने इसे हल किया है, लेकिन जैसे "मैं इसे सही कर रहा हूं" प्रश्न और प्रश्नों के लिए एक अनुस्मारक जो अटक सकता है उस में।डेल्फी स्टैक misalignment + com marshalling = गलत marshalling

बाहर निकलता है, डेल्फी स्टैक पर चर संरेखित नहीं करता है और इस व्यवहार को नियंत्रित करने के लिए कोई निर्देश/विकल्प नहीं हैं। मेरे एक्सपी एसपी 3 पर डिफॉल्ट COM मार्शलर को रिकॉर्ड करते समय 4-बाइट संरेखण की आवश्यकता होती है। इससे भी बदतर, जब यह असाइन किए गए पॉइंटर से मुकाबला करता है, तो यह कोई त्रुटि नहीं देता है, ओह नहीं: यह पॉइंटर को निकटतम 4-बाइट सीमा तक ले जाता है और इस तरह जारी रहता है।

इसलिए, यदि आप एक रिकॉर्ड पास करते हैं तो आपने संदर्भ द्वारा COM-marshaled फ़ंक्शन में स्टैक पर आवंटित किया है, तो आप खराब हो गए हैं और आपको यह भी पता नहीं चलेगा।

समस्या को आवंटित करने के लिए नई/निपटान का उपयोग करके हल किया जा सकता है, क्योंकि स्मृति प्रबंधक 8 बाइट्स या बेहतर पर सबकुछ संरेखित करते हैं, लेकिन भगवान, यह कष्टप्रद भाग और "ट्रिम-डाउन पॉइंटर्स" " अंश।

क्या यह वास्तव में कारण है, या क्या मैं कहीं गलत हूं?

अद्यतन: पुन: पेश करने के लिए (Win32 के लिए डेल्फी 2007)।

uses SysUtils; 

type 
    TRec = packed record 
    a, b, c, d, e: int64; 
    end; 

    TDummy = class 
    protected 
    procedure Proc(param1: integer); 
    end; 

procedure TDummy.Proc(param1: integer); 
var a, b, c: byte; 
    rec: TRec; 
begin 
    a := 5; 
    b := 9; 
    c := 100; 

    rec.a := param1; 
    rec.b := a; 
    rec.c := b; 
    rec.d := c; 
    writeln(IntToHex(integer(@rec), 8)); 
    readln; 
end; 

var Obj: TDummy; 
begin 
    obj := TDummy.Create; 
    try 
    obj.Proc(0); 
    finally 
    FreeAndNil(obj); 
    end; 
end. 

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

COM के साथ भाग पुन: पेश करना आसान है लेकिन व्याख्या करने में लंबा है। नमूना सर्वर नामक एक नया वीसीएल ऐप बनाएं, एक COM ऑब्जेक्ट नमूना ऑब्जेक्ट लागू करें ISampleObject, टाइप लाइब्रेरी, फ्री-थ्रेडेड, सिंगल इंस्टेंस के साथ (सुनिश्चित करें कि ISampleObject को टाइप लाइब्रेरी में ओले ऑटोमेशन के रूप में चिह्नित किया गया है)। टाइप लाइब्रेरी खोलें, पांच __int64 फ़ील्ड के साथ एक नया नमूना रिकॉर्ड घोषित करें। ISampleObject के लिए एक नमूना रिकॉर्ड * आउट पैरामीटर के साथ एक नमूना समारोह जोड़ें। TSampleObject में SampleFunction लागू लौटने तय मूल्यों से:

function TSampleObject.SampleFunction(out rec: SampleRecord): HResult; 
begin 
    rec.a := 1291; 
    rec.b := 742310; 
    //... 
    Result := S_OK; 
end; 

नोट कैसे डेल्फी "पैक रिकॉर्ड" स्वचालित रूप से उत्पन्न प्रकार लायब्रेरी हैडर कोड में के रूप में वाणी SampleRecord:

SampleRecord = packed record 
    a: Int64; 
    b: Int64; 
    //... 
end; 

मैं जाँच की है, और यह कम से कम , डेल्फी 2010 में तय किया गया था। स्वचालित रूप से जेनरेट किए गए रिकॉर्ड वहां पैक नहीं होते हैं।

COM सर्वर पंजीकृत करें। चलाओ।

अब (नमूना 1) ऊपर स्रोत को संशोधित बस कर writeln के बजाय इस सर्वर कॉल करने के लिए:

uses SysUtils, Windows, ActiveX, SampleServer_TLB; 

procedure TDummy.Proc(param1: integer); 
var a, b, c: byte; 
    rec: SampleRecord; 
    Server: ISampleObject; 
begin 
    a := 5; 
    b := 9; 
    c := 100; 

    rec.a := param1; 
    rec.b := a; 
    rec.c := b; 
    rec.d := c; 
    Server := CoSampleObject.Create; 
    hr := Server.SampleFunction(rec); 
    writeln('@: 'IntToHex(integer(@rec), 8)+', rec.a='+IntToStr(rec.a)); 
    readln; 
end; 

var Obj: TDummy; 
begin 
    CoInitializeEx(nil, COINIT_MULTITHREADED); 
    obj := TDummy.Create; 
    try 
    obj.Proc(0); 
    finally 
    FreeAndNil(obj); 
    CoUninitialize(); 
    end; 
end. 

गौर करें कि जब आरईसी का पता मेल नहीं किया गया, आरईसी फ़ील्ड के मानों का गलत हैं (विशेष रूप से, 8, 16 या 24 बिट्स तक बिट्सफ़िफ्ट किया गया, कभी-कभी अगले मान पर लपेटा जाता है)।

+0

डेल्फी का कौन सा संस्करण, मेमोरी मैनेजर क्या है? क्या आप एक उदाहरण प्रदान कर सकते हैं जिसे हम आजमा सकते हैं? –

+0

डेल्फी 2007, फास्टएमएम 4 के बाहर बॉक्स। उदाहरण जोड़े गए। – himself

+1

कृपया इस परीक्षण मामले के साथ गुणवत्ता केंद्र में एक रिपोर्ट दर्ज करें; http://qc.embarcadero.com –

उत्तर

8

क्या आपके पास स्टैक का गलत उदाहरण है? डेल्फी को 4 बाइट सीमाओं में सबकुछ संरेखित करना चाहिए। एकमात्र मामला जिसे मैं सोच सकता हूं, गलत तरीके से गलत होगा क्योंकि कॉल-चेन के साथ कुछ जगह कुछ असेंबलर कोड है जिसने स्पष्ट रूप से इसे गलत तरीके से संरेखित करने के लिए कुछ किया है।

+0

क्या पैक किए गए रिकॉर्ड में कोई फ़ील्ड संभव हो सकता है, या बाइट एक सरणी कह सकता है? –

+1

यह होगा, लेकिन यह स्टैक स्टोरेज से कैसे संबंधित होगा? –

+1

@Allen - बस एक दोस्ताना अनुस्मारक है कि परिवर्तनीय और कोड संरेखण विकल्प (एसएसपी 16-बाइट सीमा संरेखण की अनुमति देने के लिए) _highly_ वांछनीय होगा। – PhiS

संबंधित मुद्दे