সংকলনের সময় মুছে ফেলার অপব্যবহার সনাক্তকরণ [] বনাম। মোছা


19

deleteসংকলনের সময় নীচে মন্তব্য করা ত্রুটি সনাক্ত করা সম্ভব কিনা তা আমি জানতে চাই ? বিশেষত, আমি জি ++ সংকলক সম্পর্কে শুনতে চাই।

ClassTypeA *abc_ptr = new ClassTypeA[100];  
abc_ptr[10].data_ = 1;  
delete abc_ptr; // error, should be delete []  

7
আপনার যেকোনোভাবে ম্যানুয়ালি মুছতে কল করা উচিত নয়।
মার্টিন ইয়র্ক

9
@ লোকীআস্টারি আপনি কি মন্তব্যটি সহায়ক বলে মনে করেছিলেন?
জেমস

5
@ জেমস: হ্যাঁ কীটি হ'ল "ম্যানুয়ালি"।
মার্টিন ইয়র্ক

কখনও কখনও এটি মেনে চলা প্রচুর লিগ্যাসি কোড পুনর্লিখনের সাথে জড়িত
নিক কেইগলি

ব্যবহার করুন std::unique_ptr<ClassTypeA[]>এবং তারপরে আপনার প্রয়োজন হবে না।
ব্যবহারকারী 253751

উত্তর:


6

সাধারণভাবে, সংকলক এই জাতীয় ত্রুটি সনাক্ত করতে পারে না। উদাহরণ: ধরুন কিছু শ্রেণীর জন্য কনস্ট্রাক্টর কিছু ডেটা সদস্যকে ব্যবহার করে বরাদ্দ দেয় new TypeName[]তবে ডেস্ট্রাক্টর ভুলভাবে এর deleteপরিবর্তে ব্যবহার করে delete[]। যদি কনস্ট্রাক্টর এবং ডেস্ট্রাক্টর পৃথক সংকলন ইউনিটগুলিতে সংজ্ঞায়িত হয়, তবে কম্প্রাইলারটি কীভাবে কনস্ট্রাক্টরকে সংজ্ঞায়িত করে যে পৃথক সংকলিত ফাইলটিতে ব্যবহারের সাথে বেমানান রয়েছে এমন সংকলক ফাইলটিকে সংকলন করার সময় তা কীভাবে জানবেন?

জিএনইউ সংকলকগুলির ক্ষেত্রে এটি হয় না। উপরে উল্লিখিত হিসাবে, এটি সাধারণ ক্ষেত্রে এটি করতে পারে না। কোনও সংকলককে এ জাতীয় মিল / নতুন মুছে ফেলার ত্রুটিগুলি সনাক্ত করতে হবে না কারণ এটি নির্ধারিত আচরণ। ইউবি হ'ল সংকলক বিক্রেতার "জেল থেকে মুক্ত" কার্ড।

ভালগ্রাইন্ডের মতো সরঞ্জামগুলি এই জাতীয় নতুন / মুছে ফেলা মেলে না তা সনাক্ত করতে পারে এবং রানটাইমে এটি করে। একটি স্থিতিশীল বিশ্লেষণ সরঞ্জাম থাকতে পারে যা উত্স ফাইলগুলির সকলের দিকে নজর রাখে যা শেষ পর্যন্ত একটি এক্সিকিউটেবল গঠনের জন্য সংকলিত হবে তবে আমি এই জাতীয় ত্রুটি সনাক্তকারী কোনও স্থির বিশ্লেষণ সরঞ্জামের মধ্যে নেই don't


আমি প্যারাসফট নামে একটি স্ট্যাটিক বিশ্লেষণ সরঞ্জাম ব্যবহার করেছি যা অবশ্যই এই নির্দিষ্ট দৃশ্যের জন্য একটি নিয়ম করে। এটি কোনও নির্দিষ্ট প্রকল্পের সমস্ত ফাইলের মধ্যে চলতে পারে (যদি এটি সঠিকভাবে কনফিগার করা থাকে)। এটি বলা হচ্ছে, আমি নিশ্চিত নই যে এটি কিলিয়ান ফোথের উত্তর সম্পর্কে পিট কারখমের মন্তব্য মতো পরিস্থিতিগুলি কতটা ভালভাবে পরিচালনা করে।
Velociraptors

28

আপনি যথাযথ RAII ক্লাস ব্যবহার করতে পারেন delete। এটি করার একমাত্র নিরাপদ উপায় এবং এই ত্রুটিটি কেবল একটির মধ্যে খুব বেশি, আপনি deleteনিজেকে কল করার মুখোমুখি হবেন ।

গতিশীল আজীবন সংস্থানগুলি পরিচালনা করতে সর্বদা ক্লাস ব্যবহার করুন এবং টাইপ সিস্টেমটি সঠিক সংস্থান ধ্বংসকে কার্যকর করবে enforce

সম্পাদনা: "আপনি যদি কোডটি অডিট করছেন এবং এটি পরিবর্তন করতে না পারেন তবে কী হবে?" তুমি চুদছ


18
-1 কারণ এটি আসলে প্রশ্নের উত্তর দেয় না।
ম্যাসন হুইলার

2
অমিলটি সনাক্ত করার একমাত্র উপায় হ'ল টাইপ সিস্টেমটি ব্যবহার করা, যা RAII ক্লাস ব্যবহার করে।
ডেড এমজি

9
... যে আরও কম বোধ করে। একটি রানটাইম মেকানিজম - RAII ক্লাসগুলির ব্যবহার স্থির টাইপ সিস্টেমের তথ্যগুলির সাথে কী করতে পারে যা সংকলকটি সংকলন সময়ে জানে?
ম্যাসন হুইলার

6
@ ম্যাসনওহিলার বুস্ট :: শেয়ারড_পিটার এবং বুস্ট :: শেয়ারড_আরে উদাহরণ হিসাবে দেখুন। ভাগ করা_পিটারটি ধ্বংস করা অবজেক্টটিকে মুছে ফেলে, ভাগ করা_আররে মোছা [] এর অ্যারে ধ্বংস করে। আপনি একটি ভাগ করা_আরকে কোনও শেয়ারড_পিটারে বরাদ্দ করতে পারবেন না, যতক্ষণ না আপনি প্রথমদিকে আরে দিয়ে একটি শেয়ারড_পিটার তৈরি না করেন - টাইপ সিস্টেমটি ভুল মুছাটি ব্যবহার করা রোধ করে।
পিট কিরখাম

4
সাধারণত, এর মতো উত্তর সহায়কের চেয়ে বেশি বেহাল। যাইহোক, এই ক্ষেত্রে, এটি আসলে সত্য। তিনি একটি সাধারণ ত্রুটির সংকলক প্রয়োগের সন্ধান করছেন, এবং আরআইআইআই সঠিকভাবে ব্যবহার করা এই শৈলীর ত্রুটিটিকে সঠিকভাবে প্রতিরোধ করে, যার ফলে তিনি তাকে যা চান ঠিক তা প্রদান করে। +1
রিওয়ালক

10

এই বিশেষ ত্রুটি - হ্যাঁ। এই ধরণের ত্রুটি সাধারণত: দুর্ভাগ্যক্রমে, না! এটি বাস্তবায়িত না করে মৃত্যুদণ্ডের প্রবাহ সম্পর্কে ভবিষ্যদ্বাণী করা জড়িত এবং এটি নির্বিচারে প্রোগ্রামগুলির পক্ষে সম্ভব নয়। (এজন্য বেশিরভাগ সংকলক আপনার উদাহরণের মতো সাধারণ কেসগুলি সনাক্ত করার চেষ্টাও করে না))

অতএব ডেডএমজির উত্তরটি যথাযথ একটি: মনোযোগ দিয়ে এটিকে সঠিক করার চেষ্টা করবেন না - মানুষের দৃষ্টি আকর্ষণীয়। ভাষা-সরবরাহিত উপায়গুলি ব্যবহার করুন এবং কম্পিউটারকে মনোযোগ দিন।


এটি কীভাবে কার্যকর করার প্রবাহের পূর্বাভাসের প্রয়োজন? এটিকে আমার কাছে সম্পূর্ণ স্থিতিশীল, সংকলন-সময় জ্ঞানের মতো মনে হচ্ছে; সংকলকটির টাইপ সিস্টেমটি জানে যে অ্যারে কী এবং কী নয়।
ম্যাসন হুইলার

এমনকি কাস্টসের উপস্থিতিতেও? দুঃখিত, আমি যদি ভুল বুঝতে পারি তবে আমি উত্তরটি মুছব।
কিলিয়ান ফট

12
@ ম্যাসনওহিলার স্ট্যাটিক ধরণের abc_ptr ClassTypeA*তাই আপনি নতুন এবং মুছার মধ্যে একটি লাইন সন্নিবেশ করতে পারেন if ( rand() % 2 == 1 ) abc_ptr = new ClassTypeA;স্ট্যাটিক টাইপ সিস্টেমে কিছুই কিছুই দেখায় না abc_ptrযে কোনও অ্যারে বা গতিশীল অবজেক্টে বা অন্য অবজেক্টে বা অ্যারেতে অংশের দিকে বিন্দু রয়েছে কিনা ।
পিট কিরখাম

...হ্যাঁ সঠিক. আমি সত্যিকারের অ্যারের প্রকারের সাথে ভাষা নিয়ে কাজ করতে এতটাই অভ্যস্ত যে সি-ল্যান্ডে এটি কীভাবে শেষ হয়েছে তা ভুলে যেতেই থাকি। :(
ম্যাসন হুইলারের

1
@ পিট কির্খাম, @ ম্যাসন হুইলারের: তবে এখনও রানটাইমটি দেখতে হবে যে ঠিকানার ঠিকানায় কতটি বস্তু সঞ্চিত রয়েছে abc_ptr, অন্যথায় কীভাবে এটি সঠিক পরিমাণের স্মৃতিশক্তি হ্রাস করতে সক্ষম হবে? সুতরাং রানটাইম জানে যে কতগুলি অবজেক্ট অবশ্যই ডিলোক্যাট করা উচিত।
জর্জিও

4

আপনি যে তুচ্ছ ঘটনা দেখান তা সংকলনের সময় সনাক্ত করা যায়, কারণ বস্তুর তাত্পর্য এবং ধ্বংস একই সুযোগে রয়েছে। সাধারণভাবে, মুছে ফেলা ইনস্ট্যান্টেশন হিসাবে একই স্কোপ বা এমনকি একই উত্স ফাইলটিতে নেই। এবং একটি সি ++ পয়েন্টারের ধরণটি তার ধরণের একক অবজেক্টের বা অ্যারের উল্লেখ করে কিনা তা নিয়ে তথ্য বহন করে না, বরাদ্দকরণের প্রকল্পটি ছেড়ে দেওয়া হোক। সুতরাং সাধারণভাবে সংকলনের সময় এটি নির্ণয় করা সম্ভব নয়।

কেন সম্ভব যে বিশেষ মামলাগুলি সনাক্ত করা যায় না?

সি ++ তে ইতিমধ্যে স্মৃতি পয়েন্টার এবং উচ্চ স্তরের অ্যারে ( std::vector) এর সাথে যুক্ত গতিশীল সংস্থানগুলির ফুটো নিয়ে কাজ করার জন্য সরঞ্জাম রয়েছে ।

আপনি যদি সঠিক deleteগন্ধ ব্যবহার করেন তবে আপনার কোডটি এখনও ব্যতিক্রম নিরাপদ নয়। যদি মধ্যবর্তী কোড new[]এবং delete[]একটি গতিশীল প্রস্থান দ্বারা বন্ধ-বড় অক্ষরজনিত সমস্যার কখনো সঞ্চালন করে।

রান-টাইম সনাক্তকরণ যতদূর যায়, Valgrindসরঞ্জামটি রান-টাইমে এটি সনাক্তকরণের জন্য ভাল কাজ করে। ঘড়ি:

==26781== Command: ./a.out
==26781==
==26781== Mismatched free() / delete / delete []
==26781==    at 0x402ACFC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26781==    by 0x8048498: main (in /home/kaz/test/a.out)
==26781==  Address 0x4324028 is 0 bytes inside a block of size 80 alloc'd
==26781==    at 0x402B454: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26781==    by 0x8048488: main (in /home/kaz/test/a.out)

অবশ্যই, ভালগ্রাইন্ড সমস্ত প্ল্যাটফর্মে চালিত হয় না, এবং সরঞ্জামের অধীনে সমস্ত রান-সময় পরিস্থিতি পুনরুত্পাদন করা সবসময় ব্যবহারিক বা সম্ভব নয়।


আপনি বলছেন যে এই তুচ্ছ ঘটনাটি সংকলনের সময় সনাক্ত করা যায়। আপনি কি দয়া করে আমাকে বলতে পারেন যে এটি অর্জনের জন্য আপনি কোন সংকলন আদেশটি ব্যবহার করেন?
SebGR

"সংকলনের সময় সনাক্ত করা যায়" এর অর্থ এখানে একটি সংকলকটিতে কার্যকর করা সহজ, জি ++ এর এটি নয়। এই স্কোপটি প্রক্রিয়া করার সময় একটি সংকলকটির আঁকড়ে ধরে রাখার পুরো আজীবন থাকে এবং সিনট্যাক্সের সাথে আবদ্ধ সিঁটিক বৈশিষ্ট্য হিসাবে বরাদ্দ তথ্য প্রচার করতে পারে।
কাজ

-3

সংকলন-সময় / স্থির-বিশ্লেষণ-সময় সনাক্তকরণের কিছু তুচ্ছ উদাহরণ:

সাথে একটি RHEL7 হোস্টে cppcheck 1.77 and 1.49

> cat test.cc
#include <memory>
int main(){char* buf = new char[10];delete buf;}

http://cppcheck.sourceforge.net/

> cppcheck -x c++ test.cc
Checking test.cc ...
[test.cc:2]: (error) Mismatching allocation and deallocation: buf

সঙ্গে clang++ 3.7.1RHEL7 উপর

> clang++ --analyze -x c++ test.cc
test.cc:2:37: warning: Memory allocated by 'new[]' should be deallocated by
'delete[]', not 'delete'
int main(){char* buf = new char[10];delete buf;}
                                    ^~~~~~~~~~
1 warning generated.

ক্ল্যাং স্ট্যাটিক বিশ্লেষক কখন std::unique_ptrপাস না হয় তা সনাক্ত করতে পারে<char[]>

> cat test2.cc
#include <memory>
int main(){std::unique_ptr<char> buf(new char[10]);}

https://clang-analyzer.llvm.org/

> clang++ --analyze -x c++ -std=c++11 test2.cc
In file included from test2.cc:1:
In file included from /opt/rh/devtoolset-4/root/usr/lib/gcc/x86_64-redhat-linux/5.3.1/
../../../../include/c++/5.3.1/memory:81:
/opt/rh/devtoolset-4/root/usr/lib/gcc/x86_64-redhat-linux/5.3.1/
../../../../include/c++/5.3.1/bits/unique_ptr.h:76:2: 
warning: Memory allocated by
      'new[]' should be deallocated by 'delete[]', not 'delete'
        delete __ptr;
        ^~~~~~~~~~~~
1 warning generated.

এটিকে ঝাঁকুনিতে যুক্ত করা টেস্টগুলি এবং পরীক্ষাগুলি এবং একটি বাগ খুঁজে পেয়েছি এমন কাজের লিঙ্ক সহ নীচে আপডেট করুন।

এই reviews.llvm.org/D4661 সঙ্গে ঝনঝন জোড়া হয়েছে - "mismatching সনাক্ত 'নতুন' এবং 'ডিলিট' ব্যবহার করে"

পরীক্ষাগুলি পরীক্ষা / বিশ্লেষণ / মিসমেডডেলোলোকেটার-চেকার-টেস্ট.মিমি থাকে

আমি এই খোলা বাগটি পেয়েছি - bugs.llvm.org/show_bug.cgi?id=24819


কেউ সন্দেহ করে না যে আপনি কোনও স্থির বিশ্লেষক খুঁজে পেতে পারেন যা একটি নির্দিষ্ট ভুল ব্যবহার সনাক্ত করে, তার পরিবর্তে এমন একটি যা সমস্ত ভুল ব্যবহার সনাক্ত করে (এবং আশা করি কোনও ভুল ব্যবহারের ভুল নেই )
ক্যালথ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.