2017-10-24 12 views
11

के कारण मैं एक प्रक्रिया है कि एक पैरामीटर के रूप एक गतिशील सरणी TData = TArray<Byte> लेता है।गतिशील सरणी गलत सूचक अपवाद

procedure DoStuff(const Input: TData); 
begin 
    // do nothing 
end; 

और एक फ़ंक्शन जो गतिशील सरणी देता है।

function SomeData: TData; 
begin 
    Result := [1, 2]; 
end; 

जब मैं नीचे दिए गए उदाहरण में प्रक्रिया का उपयोग करें, DoStuff निम्न डेटा हो जाता है (1, 2, 3, 1, 3) लेकिन मैं एक EInvalidPointer अपवाद DoStuff पूर्ण होने के बाद मिलता है।

procedure TForm1.Button1Click(Sender: TObject); 
begin  
    DoStuff([1, 2, 3] + SomeData); 
end; 

कॉलिंग DoStuff([1, 2] + SomeData); एक त्रुटि में परिणाम नहीं करता है, यह भावुक पाने के लिए जब सरणी 4 आइटम से अधिक है लगता है। यदि मैं सरणी को पकड़ने के लिए एक temp चर का उपयोग करता हूं, तो DoStuff अभी भी (1, 2, 3, 1, 2) हो जाता है लेकिन कोई त्रुटि नहीं है।

procedure TForm1.Button2Click(Sender: TObject); 
var 
    Temp: TData; 
begin 
    Temp := [1, 2, 3] + SomeData; 

    DoStuff(Temp); 
end; 

यह सूचक अपवाद की तरह लग रहा है कि कैसे गतिशील सरणियों में से एक को मुक्त कर दिया जाता है जब वे क्षेत्र से बाहर गिर से संबंधित है।

मैं इस तरह से गतिशील सरणियों का उपयोग नहीं किया जाना चाहिए? काम करते समय, इसने मेरी वर्तमान समस्या को बहुत साफ तरीके से हल किया।

मैंने TArray<Byte>; के बजाय array of Byte; का उपयोग करने का भी प्रयास किया है, लेकिन इसका परिणाम भी था।

पूर्ण परीक्षण इकाई:

unit Main; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, 
    System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; 

type 
    TData = TArray<Byte>; 

    TForm1 = class(TForm) 
    Button1: TButton; 
    Button2: TButton; 
    procedure Button1Click(Sender: TObject); 
    procedure Button2Click(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

procedure DoStuff(const Input: TData); 
function SomeData: TData; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    DoStuff([1, 2, 3] + SomeData); 
end; 

procedure TForm1.Button2Click(Sender: TObject); 
var 
    Temp: TData; 
begin 
    Temp := [1, 2, 3] + SomeData; 

    DoStuff(Temp); 
end; 

procedure DoStuff(const Input: TData); 
begin 
    // do nothing 
end; 

function SomeData: TData; 
begin 
    Result := [1, 2]; 
end; 

end. 

उत्तर

8

आपका कोड नहीं दोष है और किसी भी त्रुटि केवल संकलक/RTL कीड़े की वजह से हो सकता है।

गतिशील सरणी अक्षरों के लिए समर्थन और गतिशील सरणी + ऑपरेटर पहले रिलीज़ होने पर कुछ हद तक कमजोर था। इन सुविधाओं को XE7 में जोड़ा गया था और मेरा मानना ​​है कि अधिकांश बग XE8 द्वारा बाहर निकाले गए थे।

मेरा अनुमान है कि आप XE7 का उपयोग कर रहे हैं, या शायद एक परत संस्करण जिसमें अभी भी XE7 के कई स्पष्ट लोगों की तुलना में अधिक अस्पष्ट बग शामिल है।

आपके विकल्प होने लगते हैं: एक बाद डेल्फी संस्करण के लिए

  1. अद्यतन। गतिशील सरणियों और/या गतिशील सरणी शाब्दिक साथ + ऑपरेटर के उपयोग से बचने के कोड के आसपास
  2. कार्य करें।

मैं अभी भी XE7 का उपयोग करता हूं और अपने सामान्य जेनेरिक कॉन्सटेनेशन फ़ंक्शन के साथ समस्याओं को हल करता हूं। ऐसा करने का एक उदाहरण यहां दिया जा सकता है: https://stackoverflow.com/a/15924484/505088

इस तरह की कार्यप्रणाली आपको + ऑपरेटर के साथ समस्याओं से बचने में मदद करती है, लेकिन यदि समस्या सरणी अक्षरों को संभालने के साथ नहीं है। यदि आपकी समस्या सरणी अक्षरों के साथ है तो आप [1, 2, 3] के स्थान पर TData.Create(1, 2, 3) का उपयोग करने की आवश्यकता समाप्त कर सकते हैं।

यदि दोष बाद के संस्करणों में मौजूद है तो कृपया एम्बरकेडेरो के गुणवत्ता पोर्टल पर एक बग रिपोर्ट सबमिट करें।

+2

डेल्फी 10.2 बर्लिन में एक ही त्रुटि है। System._DynArray को कॉल करते समय होता है जब बटन 1 क्लिक समाप्त होता है। –

+0

सुधार, 10.2 टोक्यो यह है। –

+1

मैं इसे Win32 पर 10 सिएटल पर भी पुन: उत्पन्न कर सकता हूं, लेकिन Win64 नहीं। इसके अलावा 'टेकडाटा (लोकलएरे + [4, 5, 6])' ठीक काम करता है जबकि 'टेकडाटा ([4, 5, 6] + लोकलएरे);' नहीं। –

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