delphi - क्या मैं आरटीएल क्लास सिस्टम में लगातार सुधार कर सकता हूँ। क्लासेस। टीट्रीम और डेल्फी एक्सई 6 में रनटाइम पर इसे फिर से बनाया?




delphi-xe6 (2)

मैं System.Classes.pas में ज्ञात बदसूरत प्रदर्शन सीमा के आसपास काम करने की कोशिश कर रहा हूं, जिसकी 1 9 80 के युग निरंतर बफर सीमा ($ F000) है जो इस तरह दिखती है:

function TStream.CopyFrom(const Source: TStream; Count: Int64): Int64;
const
  MaxBufSize = $F000;
....

यह हमारे डेल्फी आवेदन में प्रमुख प्रदर्शन दंड पैदा कर रहा है। डेल्फी XE2 में XE5 के माध्यम से, हम इसे संशोधित करने और निम्नलिखित तरीकों में से एक का उपयोग करने में सक्षम थे:

  • मैं डेल्फी स्रोतों को संशोधित कर सकता हूं, और फिर बैच फ़ाइल से dcc32.exe को खोलकर, डेल्फी लाइब्रेरी फ़ोल्डर में System.Classes.dcu फ़ाइल का पुनर्निर्माण कर सकता है। मुझे पता है कि यह बदसूरत है और मुझे ऐसा करना पसंद नहीं था, लेकिन मुझे आरटीएल में इस बदसूरत प्रदर्शन के मुद्दे को पसंद नहीं है, और हमारे उपयोगकर्ता प्रदर्शन सिरदर्दों के साथ नहीं रह सकते हैं, जो इसका कारण बनता है।

  • मैं एक संशोधित प्रणाली डाल करने की कोशिश कर सकता हूं।

उपरोक्त तरीकों से मेरे लिए डेल्फी XE6 में अब काम नहीं कर रहा है, संभवतः कुछ आंतरिक कंपाइलर परिवर्तनों के लिए धन्यवाद। मुझे कम से कम कमांड लाइन एप्लिकेशन में त्रुटि मिलती है जिसमें सिस्टम शामिल होता है। कंटेनर्स में इसका उपयोग खंड है, यह है:

[dcc32 Fatal Error] System.Classes.pas(19600): F2051 Unit System.Contnrs was compiled with a different version of System.Classes.TComponent

इस समस्या को पुन: उत्पन्न करने के लिए नमूना कार्यक्रम (मान लें कि आपने सिस्टम को संशोधित किया है। क्लासेस। और मैक्सब्यूफ़सिज़ स्थिरांक बदल दिया है), यहां दिखाया गया है:

program consoletestproject;

{$APPTYPE CONSOLE}

{$R *.res}

uses
   System.Contnrs,
   System.SysUtils;

var
  List:System.Contnrs.TObjectList;
begin
   WriteLn('Hello world');
end.

दोबारा, यह समस्या डेल्फी XE6 में आसानी से प्रजनन करती है, लेकिन XE5, या पहले में कोई समस्या नहीं है।

अनुशंसित अभ्यास क्या है जब आप सिस्टम की एक प्रतिलिपि प्रतिलिपि का उपयोग करके मौलिक आरटीएल या वीसीएल सीमा के आसपास बिल्कुल काम करना चाहिए। क्लासेस। या सिस्टम। एसयूएसयूटील्स। या कुछ अन्य बहुत कम स्तर इकाई? (हां, मुझे पता है कि आपको ऐसा नहीं करना चाहिए अगर आपको नहीं करना है, तो व्याख्यान के साथ परेशान न करें।)

क्या आप कमांड लाइन पर "dcc32.exe" के माध्यम से कमांड लाइन पैरामीटर का एक जादू सेट उपयोग कर सकते हैं, जो संशोधित डीसीयू का उत्पादन कर सकता है जो उपरोक्त आवेदन के उदाहरण के साथ ठीक से लिंक होगा?

एक द्वितीयक प्रश्न के रूप में, उन डीसीयू फाइलें हैं जिनके लिए कोई स्रोत मौजूद नहीं है, जब कोई ऐसा करने का प्रयास करेगा, तो उस स्थिति में ऊपर दिए गए सभी उत्तर का जवाब होगा, "आप इसे ठीक नहीं कर सकते, और यदि कोई बग है आरटीएल में, आप भाग्य से बाहर हैं? "

एक संभव समाधान आपके परियोजना खोज पथ (या लाइब्रेर पथ) में "$ (बीडीएस) \ स्रोत \ rtl \ common" को शामिल करना है, प्रत्येक टूटी (आवश्यक रीकंपाइल) डीसीयू को प्रत्येक समय के पुनर्निर्माण के लिए मजबूर करना, लेकिन यह बदसूरत और गलत लगता है


आप इस सीमा को एक चक्कर का उपयोग करके दूर कर सकते हैं, इस नमूने की कोशिश करें जो Delphi Detours Library का उपयोग करता है

सबसे पहले हुक करने के लिए विधि के हस्ताक्षर को परिभाषित करें

var
 Trampoline_TStreamCopyFrom : function (Self : TStream;const Source: TStream; Count: Int64): Int64 = nil;

फिर चक्कर लागू करें

function Detour_TStreamCopyFrom(Self : TStream;const Source: TStream; Count: Int64): Int64;
const
  MaxBufSize = 1024*1024; //use 1 mb now :)
var
  BufSize, N: Integer;
  Buffer: TBytes;
begin
  if Count <= 0 then
  begin
    Source.Position := 0;
    Count := Source.Size;
  end;
  Result := Count;
  if Count > MaxBufSize then BufSize := MaxBufSize else BufSize := Count;
  SetLength(Buffer, BufSize);
  try
    while Count <> 0 do
    begin
      if Count > BufSize then N := BufSize else N := Count;
      Source.ReadBuffer(Buffer, N);
      Self.WriteBuffer(Buffer, N);
      Dec(Count, N);
    end;
  finally
    SetLength(Buffer, 0);
  end;
end;

अंत में मूल समारोह को ट्रम्पोलिन से बदलें (आप कुछ कोड के प्रारंभिक भाग में इस कोड का उपयोग कर सकते हैं)

  Trampoline_TStreamCopyFrom     := InterceptCreate(@TStream.CopyFrom,   @Detour_TStreamCopyFrom);

और हुक को छोड़ने के लिए जो आप उपयोग कर सकते हैं

 if Assigned(Trampoline_TStreamCopyFrom) then
   InterceptRemove(@Trampoline_TStreamCopyFrom);

अपडेट 1: नीचे सुझाव XE6 में Classes यूनिट के लिए काम नहीं करता है। मूल तकनीक ध्वनि है और इसी तरह की समस्याओं का समाधान करती है। लेकिन XE6 के लिए, कम से कम Classes यूनिट, यह तुरंत स्पष्ट नहीं है कि इसे कैसे पुन: संकलन करना है।

यह एक गलती है जिसे एक्सई 6 में पेश किया गया है क्योंकि यह तकनीक काम करने के लिए होती है और इसे आधिकारिक तौर पर एम्बारकाडरो द्वारा अनुमोदित किया जाता है: http://blog.marcocantu.com/blog/2014_august_buffer_overflow_bitmap.html

अपडेट 2:

XE7 में, यह समस्या अब मौजूद नहीं है। यह प्रकट होगा कि XE6 में जो कुछ भी टूटा गया था वह तय हो चुका है।

जब आप एम्बर्सैडरो द्वारा यूनिकर संकलित किए गए थे, तो उनको मैच करने के लिए संकलक विकल्पों की आवश्यकता होती है यही कारण है कि आपका कार्यान्वयन अनुभाग केवल तब ही असफल हो जाता है जब ऐसा लगता है जैसे उसे सफल होना चाहिए।

एक डिफ़ॉल्ट प्रोजेक्ट प्रारंभ करें और इन विकल्पों को बनाने के लिए CTRL + O + O का उपयोग करें। मुझे मिला

{$A8,B-,C+,D+,E-,F-,G+,H+,I+,J-,K-,L+,M-,N-,O+,P+,Q-,R-,S-,T-,U-,V+,W-,X+,Y+,Z1}

जब मैं यह XE6 में करता हूँ

उस यूनिट की अपनी प्रतिलिपि के शीर्ष पर रखें और आपको जाना अच्छा लगेगा संभवतः आप अपने मेजबान प्रोजेक्ट विकल्पों के आधार पर इनमें से कट-डाउन उपसमुच्चय के साथ भाग ले सकते हैं। मेरे कोड में मुझे लगता है कि:

{$R-,T-,H+,X+}

पर्याप्त होता।







delphi-xe6