বৈধতার জন্য পরীক্ষার পয়েন্টার (সি / সি ++)


91

প্রদত্ত পয়েন্টারটি "বৈধ" হলে নিখুঁতভাবে (প্রগ্রেমেটিকালি অবশ্যই) কোনও উপায় আছে? NULL অনুসন্ধান করা সহজ, তবে 0x00001234 এর মতো জিনিসের কী হবে? এই ধরণের পয়েন্টারকে ডিফারেন্স করার চেষ্টা করার সময় একটি ব্যতিক্রম / ক্রাশ ঘটে।

একটি ক্রস প্ল্যাটফর্ম পদ্ধতি পছন্দ করা হয়, তবে প্ল্যাটফর্ম-নির্দিষ্ট (উইন্ডোজ এবং লিনাক্সের জন্য) ঠিক আছে।

স্পষ্টতার জন্য আপডেট: সমস্যাটি বাসি / মুক্ত / অবিচ্ছিন্ন পয়েন্টারগুলির সাথে নয়; পরিবর্তে, আমি এমন একটি এপিআই বাস্তবায়ন করছি যা কলারের কাছ থেকে পয়েন্টার নেয় (যেমন একটি স্ট্রিংয়ের কাছে পয়েন্টার, কোনও ফাইল হ্যান্ডেল ইত্যাদি)। কলার পয়েন্টার হিসাবে একটি অবৈধ মান প্রেরণ করতে পারে (উদ্দেশ্য বা ভুল করে)। আমি কীভাবে একটি ক্রাশ রোধ করব?


আরও দেখুন stackoverflow.com/questions/496034/...
ChrisW

আমি মনে করি লিনাক্সের জন্য সেরা ইতিবাচক উত্তরটি জর্জ ক্যারেটই দিয়েছেন। যদি এটি পর্যাপ্ত না হয় তবে লাইব্রেরিতে ফাংশন সিম্বল টেবিল বা তাদের নিজস্ব ফাংশন সারণী সহ উপলব্ধ গ্রন্থাগারের টেবিলের অন্য স্তরটি বিবেচনা করুন। তারপরে সেই সঠিক টেবিলগুলির বিরুদ্ধে পরীক্ষা করুন। অবশ্যই, এই নেতিবাচক উত্তরগুলিও সঠিক: আপনি যদি ব্যবহারকারী অ্যাপ্লিকেশনটিতে অনেকগুলি অতিরিক্ত বিধিনিষেধ না বদ্ধ করেন তবে কোনও ফাংশন পয়েন্টার বৈধ কিনা তা আপনি সত্যই 100% নিশ্চিত হতে পারবেন না।
মিঙ্গুয়া

এপিআই স্পেসিফিকেশন বাস্তবায়নের দ্বারা পূরণের জন্য এই ধরনের বাধ্যবাধকতাটি নির্দিষ্ট করে? যাইহোক, আমি ভেবে দেখছি না যে আপনি বিকাশকারী এবং ডিজাইনার উভয়ই are আমার বক্তব্য, আমি মনে করি না যে একটি এআইপি "আর্গুমেন্ট হিসাবে কোনও অবৈধ পয়েন্টারটি পাস করার ক্ষেত্রে, ফাংশনটি অবশ্যই সমস্যাটি পরিচালনা করবে এবং NULL প্রদান করবে" like কোনও এআইপি হ্যাকের দ্বারা নয়, যথাযথ ব্যবহারের শর্তে একটি পরিষেবা সরবরাহ করার বাধ্যবাধকতা গ্রহণ করে। তবুও, এটি কিছুটা বোকা হওয়া কোনও ক্ষতি করে না। একটি রেফারেন্স ব্যবহার করে এই ধরনের মামলাগুলি কম সর্বনাশ ছড়িয়ে পড়ে। :)
পনিরোস

উত্তর:


75

স্পষ্টকরণের জন্য আপডেট: সমস্যাটি বাসি, মুক্ত বা অবিচ্ছিন্ন পয়েন্টারগুলির সাথে নয়; পরিবর্তে, আমি এমন একটি এপিআই বাস্তবায়ন করছি যা কলারের কাছ থেকে পয়েন্টার নেয় (যেমন একটি স্ট্রিংয়ের কাছে পয়েন্টার, কোনও ফাইল হ্যান্ডেল ইত্যাদি)। কলার পয়েন্টার হিসাবে একটি অবৈধ মান প্রেরণ করতে পারে (উদ্দেশ্য বা ভুল করে)। আমি কীভাবে একটি ক্রাশ রোধ করব?

আপনি এই চেক করতে পারবেন না। পয়েন্টারটি "বৈধ" আছে কি না তা পরীক্ষা করার কোনও উপায় নেই। আপনার বিশ্বাস রাখতে হবে যে লোকেরা যখন কোনও ফাংশন ব্যবহার করে যা পয়েন্টার নেয়, তখন সেই লোকেরা জানে যে তারা কী করছে। যদি তারা আপনাকে 0x4211 পয়েন্টার মান হিসাবে পাস করে তবে আপনাকে 0x4211 ঠিকানার দিকে লক্ষ্য রাখতে হবে। এবং যদি তারা "দুর্ঘটনাক্রমে" কোনও বস্তুটিকে আঘাত করে তবে আপনি যদি কিছু ভীতিজনক অপারেশন সিস্টেম ফাংশন (ইসভালিডপিআরটি বা যে কোনও কিছু) ব্যবহার করেন, আপনি এখনও একটি বাগে পিছলে যাবেন এবং দ্রুত ব্যর্থ হবেন না।

এই জাতীয় জিনিস সিগন্যাল করার জন্য নাল পয়েন্টার ব্যবহার শুরু করুন এবং আপনার গ্রন্থাগারের ব্যবহারকারীকে বলুন যে তারা ভুলক্রমে অবৈধ পয়েন্টারগুলি গুরুতরভাবে পাস করার প্রবণতা দেখায় তারা পয়েন্টার ব্যবহার না করা উচিত :)


এটি সম্ভবত সঠিক উত্তর তবে আমি মনে করি যে একটি সাধারণ ফাংশন যা সাধারণ হেক্সস্পিক মেমরির অবস্থানগুলি পরীক্ষা করে তা সাধারণ ডিবাগিংয়ের জন্য দরকারী হবে ... এই মুহূর্তে আমার কাছে একটি পয়েন্টার রয়েছে যা মাঝে মাঝে 0xfeeeee কে দেখায় এবং যদি আমার একটি সাধারণ ফাংশন ছিল যা আমি পারতাম চারপাশে গোলমরিচর দৃ to়তার সাথে ব্যবহার করুন অপরাধীর সন্ধান করা এটি আরও সহজ করে তুলবে ... সম্পাদনা: যদিও নিজেকে অনুমান করে নিজেকে লিখতে
পারাটা

@ তবে সমস্যাটি হ'ল কিছু সি এবং সি ++ কোড চেক না করেই কোনও অবৈধ ঠিকানায় পয়েন্টার গাণিতিক কাজ করতে পারে (আবর্জনা-সংক্রান্ত, আবর্জনা-আউট টেনিটের উপর ভিত্তি করে) এবং সুতরাং সেইগুলির মধ্যে একটির থেকে "গাণিতিকভাবে সংশোধিত" পয়েন্টারটি পাস করবে অজানা ঠিকানা known একটি সাধারণ অবৈধ ঠিকানা বা কোনও ভুল ধরণের উপর ভিত্তি করে অস্তিত্বহীন ভিটিবেল থেকে সাধারণ পদ্ধতিগুলি সন্ধান করা হচ্ছে, বা কেবল বিন্দু থেকে কোনও কাঠামোর দিকে ক্ষেত্রগুলি পড়া যা একটিতে নির্দেশ করে না।
রওয়ং

এর মূলত অর্থ এই যে আপনি কেবল বাইরের বিশ্ব থেকে অ্যারে সূচকগুলি নিতে পারেন। এমন একটি এপিআই যা অবশ্যই কলার থেকে নিজেকে রক্ষা করতে পারে কেবল ইন্টারফেসে পয়েন্টার থাকতে পারে না। যাইহোক, পয়েন্টারগুলির বৈধতা (যা আপনি অভ্যন্তরীণভাবে আবদ্ধ হন) সম্পর্কে দৃ about়তার সাথে ম্যাক্রোগুলি ব্যবহার করা ভাল হবে। যদি কোনও পয়েন্টার এমন অ্যারের ভিতরে পয়েন্টার গ্যারান্টিযুক্ত থাকে যার প্রারম্ভিক বিন্দু এবং দৈর্ঘ্য জানা যায়, তবে তা স্পষ্টভাবে চেক করা যায়। ডেরেফের (অনির্ধারিত ত্রুটি) চেয়ে দাবী লঙ্ঘনের (ডকুমেন্টেড ত্রুটি) মারা যাওয়ার চেয়ে ভাল।
রব

34

লিনাক্সের অধীনে সি প্রোগ্রামের জন্য এটি তিনটি সহজ উপায় যা মেমরিটিতে এটি চলছে তার অবস্থান সম্পর্কে স্বজ্ঞাপূর্ণ জানতে এবং কেন কিছু প্রসঙ্গে এই প্রশ্নের যথাযথ পরিশীলিত উত্তর রয়েছে।

  1. Getpagesize () কল করার পরে এবং কোনও পৃষ্ঠার সীমানায় পয়েন্টারকে গোল করার পরে, আপনি কোনও পৃষ্ঠা বৈধ কিনা তা খুঁজে বের করার জন্য মিনকোর () কল করতে পারেন এবং এটি প্রক্রিয়াটির কার্যনির্বাহী অংশের অংশ হতে পারে কিনা তা খুঁজে বের করতে। নোট করুন যে এর জন্য কিছু কার্নেল সংস্থান দরকার, তাই আপনার এটি বেঞ্চমার্ক করা উচিত এবং নির্ধারণ করা উচিত যে আপনার এপিআইতে এই ফাংশনটি কল করা সত্যিই উপযুক্ত কিনা। যদি আপনার এপিআই বাধা হ্যান্ডল করতে চলেছে বা সিরিয়াল পোর্টগুলি মেমোরিতে পড়ছে, অনুমানযোগ্য আচরণগুলি এড়ানোর জন্য এটি কল করা উপযুক্ত।
  2. স্টাট () কল করার পরে কোনও / প্রোক / স্ব ডিরেক্টরি উপলব্ধ আছে কিনা তা নির্ধারণ করার পরে, আপনি কোন অঞ্চলে কোন পয়েন্টারটি থাকে সে সম্পর্কে তথ্য জানতে / proc / স্ব / মানচিত্রের মাধ্যমে খোলা এবং পড়তে পারেন। প্রোকের জন্য ম্যান পেজ, প্রক্রিয়া সম্পর্কিত তথ্য সিউডো-ফাইল সিস্টেম অধ্যয়ন করুন। স্পষ্টতই এটি তুলনামূলকভাবে ব্যয়বহুল, তবে আপনি সম্ভবত কোনও বাইনারি অনুসন্ধান ব্যবহার করে দক্ষতার সাথে অনুসন্ধান করতে পারেন এমন একটি অ্যারেতে পার্সের ফলাফল ক্যাশে দিয়ে পালাতে সক্ষম হতে পারেন। / Proc / স্ব / smaps বিবেচনা করুন। যদি আপনার এপিআই উচ্চ-পারফরম্যান্সের কম্পিউটিংয়ের জন্য থাকে তবে প্রোগ্রামটি নন-ইউনিফর্ম মেমরি আর্কিটেকচারের নুমার জন্য ম্যান পেজের আওতায় ডকুমেন্ট করা / প্রো / / স্ব / নুমা সম্পর্কে জানতে চাইবে।
  3. গেট_মম্পোলিসি (এমপিএল_এফ_এডিডিআর) কলটি উচ্চ কার্যকারিতা কম্পিউটিং এপিআই কাজের জন্য উপযুক্ত যেখানে মৃত্যুর একাধিক থ্রেড রয়েছে এবং আপনি সিপিইউ কোর এবং সকেট সংস্থার সাথে সম্পর্কিত হিসাবে অ-ইউনিফর্মের স্মৃতিতে আপনার কাজ পরিচালনা করছেন। যেমন একটি এপিআই অবশ্যই আপনাকে জানায় যে কোনও পয়েন্টারটি বৈধ কিনা।

মাইক্রোসফ্ট উইন্ডোজের অধীনে কোয়েরি ওয়ার্কিংসেটেক্স ফাংশন রয়েছে যা প্রক্রিয়া স্থিতি এপিআই এর অধীনে নথিভুক্ত করা হয়েছে (NUMA এপিআইতেও) পরিশীলিত NUMA এপিআই প্রোগ্রামিংয়ের এক তাত্পর্য হিসাবে এই ফাংশন আপনাকে সাধারণ "বৈধতার জন্য পরীক্ষার পয়েন্টার (সি / সি ++)" কাজ করতে দেয়, কারণ এটি কমপক্ষে 15 বছরের জন্য অবচিত হওয়ার সম্ভাবনা নেই।


13
প্রথম উত্তর যা নিজেই প্রশ্নটি সম্পর্কে নৈতিক হওয়ার চেষ্টা করে না এবং প্রকৃতপক্ষে এর সঠিক উত্তর দেয়। লোকেরা কখনও কখনও বুঝতে পারে না যে তৃতীয় পক্ষের লাইব্রেরিগুলিতে বা লেগ্যাসি কোডে বাগগুলি সন্ধানের জন্য এই ধরণের ডিবাগিং পদ্ধতির প্রয়োজন হয় কারণ ভ্যালগ্রাইন্ড কেবলমাত্র অ্যাক্সেস করার সময় কেবল বন্য পয়েন্টার খুঁজে পায়, যেমন আপনি নিয়মিতভাবে বৈধতার জন্য পয়েন্টার পরীক্ষা করতে চান না আপনার কোডের অন্য কোনও জায়গা থেকে ওভাররাইট করা হয়েছে এমন ক্যাশে টেবিলটিতে ...
লম্পিডু

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

31

একজন অবৈধ পয়েন্টারে প্রেরণকারীকে পাঠানোর কারণে ক্র্যাশ হওয়া রোধ করা নিরব বাগগুলি খুঁজে পাওয়া শক্ত way

আপনার এপিআই ব্যবহার করে প্রোগ্রামারটির পক্ষে এটি পরিষ্কার করার বার্তাটি লুকিয়ে রাখার পরিবর্তে ক্রাশ করে তার কোডটি বোগাস হচ্ছে তা আরও ভাল নয়?


8
যদিও কিছু ক্ষেত্রে, তাত্ক্ষণিকভাবে খারাপ পয়েন্টারটি পরীক্ষা করা যখন এপিআই বলা হয় তা হল আপনি কীভাবে তাড়াতাড়ি ব্যর্থ হন। উদাহরণস্বরূপ, এপিআই যদি কোনও ডেটা স্ট্রাকচারের মধ্যে পয়েন্টার সংরক্ষণ করে তবে এটি কেবল পরে বিবেচিত হবে? তারপরে এআইপিটি খারাপ পয়েন্টারটি পাস করার পরে কিছু এলোমেলো সময়ে ক্র্যাশ ঘটবে। সেক্ষেত্রে খুব শীঘ্রই ব্যর্থ হওয়া আরও ভাল API
পিটারফ্লিন

28

উইন 32/64 এ এটি করার একটি উপায় রয়েছে। পয়েন্টারটি পড়ার চেষ্টা করুন এবং ফলস্বরূপ এসইএইচ ছাড়টি ধরুন যা ব্যর্থতার উপরে ফেলে দেওয়া হবে। যদি এটি ছুঁড়ে না ফেলে, তবে এটি একটি বৈধ পয়েন্টার।

যদিও এই পদ্ধতির সমস্যাটি হ'ল এটি কেবলমাত্র আপনি পয়েন্টার থেকে ডেটা পড়তে পারেন কিনা তা ফিরিয়ে দেয়। এটি ধরণের সুরক্ষা বা অন্য কোনও আক্রমণকারী সংখ্যার কোনও গ্যারান্টি দেয় না। সাধারণভাবে এই পদ্ধতিটি "হ্যাঁ, আমি সেই সময়টিতে স্মৃতিতে সেই বিশেষ স্থানটি পড়তে পারি যা এখন পার হয়ে গেছে" বলার অপেক্ষা রাখে না।

সংক্ষেপে, এটি করবেন না;)

রেমন্ড চেনের এই বিষয়ে একটি ব্লগ পোস্ট রয়েছে: http://blogs.msdn.com/oldnewthing/archive/2007/06/25/3507294.aspx


4
@ টিম, সি ++ এ করার কোনও উপায় নেই।
জারেডপাড়

6
এটি কেবলমাত্র "সঠিক উত্তর" যদি আপনি "বৈধ পয়েন্টার" হিসাবে সংজ্ঞায়িত করেন তবে "অ্যাক্সেস লঙ্ঘন / সেগফোল্ট না ঘটে"। আমি এটিকে "আপনি যে উদ্দেশ্যে এটি ব্যবহার করছেন সে জন্য বরাদ্দ হওয়া অর্থবহ ডেটার পয়েন্ট" হিসাবে সংজ্ঞা দিতে পছন্দ করব আমি যুক্তি দেব যে এটি পয়েন্টার বৈধতার আরও ভাল সংজ্ঞা ...;)
জাল্ফ

পয়েন্টারটি বৈধ হলেও এইভাবে পরীক্ষা করা যায় না। থ্রেড 1 () {সম্পর্কে চিন্তা করুন .. যদি (ইসভালিডপ্রিটার (পি)) * পি = 7; ...} থ্রেড 2 () {ঘুম (1); পি মুছুন; ...}
ক্রিস্টোফার

4
@ খ্রিস্টোফার, খুব সত্য। আমার বলা উচিত ছিল "আমি এখন যে সময় পার করেছি তার স্মৃতিতে সেই বিশেষ জায়গাটি পড়তে পারি"
জারেডপাড়

@ জারেডপার: সত্যিই খারাপ পরামর্শ। কোনও গার্ড-পৃষ্ঠা ট্রিগার করতে পারে, তাই স্ট্যাকটি পরে প্রসারিত হবে না বা সমান সুন্দর কিছু হবে না।
উত্সাহক

16

আফাইকের উপায় নেই। আপনার স্মৃতি মুক্ত করার পরে সবসময় NULL এ পয়েন্টার সেট করে এই পরিস্থিতি এড়াতে চেষ্টা করা উচিত।


4
নালিতে একটি পয়েন্টার সেট করা আপনাকে সুরক্ষার ভ্রান্ত ধারণা ব্যতীত কিছুই দেয় না।

ওটা সত্যি না. বিশেষত সি ++ এ আপনি শূন্যের জন্য যাচাই করে সদস্য অবজেক্টগুলি মুছবেন কিনা তা নির্ধারণ করতে পারেন। আরও মনে রাখবেন যে, সি ++ এ নাল পয়েন্টার মুছে ফেলা বৈধ, সুতরাং বিনা শর্তে ডেস্ট্রাক্টরে অবজেক্টগুলি মুছে ফেলা জনপ্রিয়।
ফার্ডিনান্দ বায়ার

4
ইন্ট * পি = নতুন ইনট (0); int * p2 = p; পি মুছুন; p = NULL; পি 2 মুছুন; // ক্রাশ

4
জ্যাবজোনক, এবং ?? তিনি যা বলেছিলেন তা হ'ল আপনি কোনও নাল পয়েন্টার মুছতে পারেন। p2 নাল পয়েন্টার নয়, তবে এটি একটি অবৈধ পয়েন্টার। আপনার আগে এটিকে শূন্য করতে হবে।
জোহানেস স্কাউব -

4
আপনার যদি স্মৃতিতে নির্দেশিত এলিয়াস থাকে তবে সেগুলির মধ্যে একটিতে কেবল NUL সেট করা হবে, অন্যান্য উপাধি চারদিকে ঝুঁকছে।
jdehaan

7

দেখে নিন ব্যবহার করার এই এবং এই প্রশ্ন। এছাড়াও আপনি একটি কটাক্ষপাত স্মার্ট পয়েন্টার


7

এই থ্রেডে উত্তরটি খানিকটা উপরে আপ করুন:

উইন্ডোজের জন্য ইসব্যাডআরডিপিআরটি (), ইসব্যাডওরাইটপ্রিটার (), ইসব্যাডকোডপিআরটি (), ইসব্যাডস্ট্রিংপিআরটি ()।

আমার পরামর্শটি তাদের থেকে দূরে থাকুন, কেউ ইতিমধ্যে এটি পোস্ট করেছেন: http://blogs.msdn.com/oldnewthing/archive/2007/06/25/3507294.aspx

একই বিষয়ে এবং একই লেখকের অন্য একটি পোস্ট (আমার মনে হয়) এটি হ'ল: http://blogs.msdn.com/oldnewthing/archive/2006/09/27/773741.aspx ("ইসড্যাডএক্সএক্সএক্সপিআরটি সত্যই ক্র্যাশপ্রগ্রামআরডমালি বলা উচিত ")।

যদি আপনার এপিআই এর ব্যবহারকারীরা খারাপ ডেটা প্রেরণ করে তবে এটি ক্রাশ হতে দিন। যদি সমস্যাটি হয় যে পাস করা ডেটা পরে না ব্যবহার করা হয় (এবং কারণটি খুঁজে পাওয়া আরও কঠিন করে তোলে), যেখানে প্রবেশের ক্ষেত্রে স্ট্রিং ইত্যাদি লগইন করা হয়েছে সেখানে একটি ডিবাগ মোড যুক্ত করুন। যদি তারা খারাপ হয় তবে তা সুস্পষ্ট হবে (এবং সম্ভবত ক্রাশ হবে)। যদি এটি প্রায়শই ঘটতে থাকে তবে এটি আপনার API কে প্রক্রিয়া থেকে সরিয়ে ফেলার উপযুক্ত হতে পারে এবং এটিকে মূল প্রক্রিয়ার পরিবর্তে এপিআই প্রক্রিয়াটি ক্র্যাশ করতে দেয়।


সম্ভবত আর একটি উপায় _CrtIsValidHeapPointer ব্যবহার করা । পয়েন্টারটি বৈধ হলে এই ফাংশনটি সত্য ফিরে আসবে এবং পয়েন্টারটি মুক্ত হয়ে গেলে একটি ব্যতিক্রম ছুঁড়ে দেবে। নথিভুক্ত হিসাবে, এই ফাংশনটি কেবল ডিবাগ সিআরটি-তে উপলব্ধ।
ক্র্যান্ড কিং

6

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

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

আমরা পারফরম্যান্স / থ্রুপুট প্রয়োজনীয়তা এবং বিশ্বাসযোগ্যতার উপর নির্ভর করে বিভিন্ন পদ্ধতি ব্যবহার করি। সর্বাধিক পছন্দের থেকে:

  • সকেট ব্যবহার করে পৃথক প্রক্রিয়া (প্রায়শই ডেটা পাঠ্য হিসাবে পাঠানো হয়)।

  • ভাগ করা মেমরি ব্যবহার করে পৃথক প্রক্রিয়া (যদি প্রচুর পরিমাণে ডেটা পাস করতে হয়)।

  • একই প্রক্রিয়াটি বার্তার কাতারের মাধ্যমে পৃথক থ্রেড (যদি সংক্ষিপ্ত সংক্ষিপ্ত বার্তা থাকে)।

  • একই প্রক্রিয়া মেমরি পুল থেকে বরাদ্দকৃত সমস্ত পাস হওয়া ডেটা পৃথক করে।

  • সরাসরি প্রক্রিয়া কলের মাধ্যমে একই প্রক্রিয়া - মেমরি পুল থেকে বরাদ্দকৃত সমস্ত পাস করা ডেটা।

তৃতীয় পক্ষের সফ্টওয়্যারগুলির সাথে ডিল করার সময় আপনি যা করার চেষ্টা করছেন তা আমরা কখনই অবলম্বন করার চেষ্টা করি না - বিশেষত যখন আমাদের সোর্স কোডের পরিবর্তে বাইনারি হিসাবে প্লাগ-ইন / লাইব্রেরি দেওয়া হয়।

বেশিরভাগ পরিস্থিতিতে মেমরি পুল ব্যবহার করা বেশ সহজ এবং অকার্যকর হওয়ার দরকার নেই। আপনি যদি ডেটা প্রথম স্থানে বরাদ্দ করেন তবে আপনার বরাদ্দকৃত মানগুলির বিরুদ্ধে পয়েন্টারগুলি পরীক্ষা করা তুচ্ছ। আপনি বৈধ ডেটা টাইপ এবং ডেটা ওভাররনগুলি পরীক্ষা করার জন্য ডেটা আগে এবং পরে বরাদ্দ করা দৈর্ঘ্য সংরক্ষণ করতে এবং "যাদু" মানগুলি যুক্ত করতে পারেন।


5

ইউনিক্সে আপনি কার্নেল সিস্টেল ব্যবহার করতে সক্ষম হবেন যা পয়েন্টার চেক করে এবং EFAULT ফেরত দেয়, যেমন:

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdbool.h>

bool isPointerBad( void * p )
{
   int fh = open( p, 0, 0 );
   int e = errno;

   if ( -1 == fh && e == EFAULT )
   {
      printf( "bad pointer: %p\n", p );
      return true;
   }
   else if ( fh != -1 )
   {
      close( fh );
   }

   printf( "good pointer: %p\n", p );
   return false;
}

int main()
{
   int good = 4;
   isPointerBad( (void *)3 );
   isPointerBad( &good );
   isPointerBad( "/tmp/blah" );

   return 0;
}

ফিরে:

bad pointer: 0x3
good pointer: 0x7fff375fd49c
good pointer: 0x400793

ওপেন () [সম্ভবত অ্যাক্সেস] এর চেয়ে সম্ভবত আরও ভাল একটি সিস্কল ব্যবহার করা যেতে পারে, যেহেতু এটির প্রকৃত ফাইল তৈরির কোডিপথ এবং পরবর্তী ঘনিষ্ঠতার প্রয়োজন হতে পারে এমন সম্ভাবনা রয়েছে।


4
এটি একটি উজ্জ্বল হ্যাক। আমি মেমরির রেঞ্জগুলি যাচাই করার জন্য বিভিন্ন সিস্কলগুলিতে পরামর্শ দেখতে চাই, বিশেষত যদি তাদের পার্শ্ব প্রতিক্রিয়া না হওয়ার গ্যারান্টি দেওয়া যেতে পারে। আপনি বাফার পাঠযোগ্য মেমরিতে আছেন কিনা তা পরীক্ষা করতে / dev / নাল লিখতে কোনও ফাইল বর্ণনাকারী খোলা রাখতে পারতেন, তবে সম্ভবত আরও সহজ সমাধান রয়েছে। সবচেয়ে ভাল আমি খুঁজে পাচ্ছি সিমিলিংক (পিটিআর, "") যা খারাপ ঠিকানায় 14 বা ভাল ঠিকানায় 2 এ সেট করবে তবে কার্নেল পরিবর্তনগুলি যাচাইয়ের ক্রমটিকে অদলবদল করতে পারে।
প্রেস্টন

4
@ প্রিস্টন ইন ডিবি 2 আমি মনে করি আমরা unistd.h এর অ্যাক্সেস ব্যবহার করতাম ()। আমি উপরে (ওপেন) ব্যবহার করেছি কারণ এটি কিছুটা কম অস্পষ্ট, তবে আপনি সম্ভবত ঠিক বলেছেন যে ব্যবহারের জন্য অনেকগুলি সম্ভাব্য স্কাইস্কল রয়েছে। উইন্ডোজ একটি স্পষ্ট পয়েন্টার চেক এপিআই ব্যবহার করত, তবে এটি থ্রেড নিরাপদ না হয়ে পরিণত হয়েছিল (আমার মনে হয় এটি এসইএইচ ব্যবহার করার চেষ্টা করেছিল এবং তারপরে মেমরির সীমার সীমানা পুনরুদ্ধার করে))
পিটার জুট

4

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

আমার প্রয়োজনটি এই নয় যে আমি সেগমেন্টেশন ত্রুটির পরে চালিয়ে যাচ্ছি - এটি বিপজ্জনক হবে - আমি কেবল গ্রাহকের সাথে কী ঘটেছে তা অবহিত করার আগে রিপোর্ট করতে চাই যাতে তারা আমাকে দোষ দেওয়ার চেয়ে তাদের কোডটি ঠিক করতে পারে!

আমি এটি (উইন্ডোজে) এটি করতে পেরেছি: http://www.cplsplus.com/references/clibrary/csignal/signal/

সংক্ষিপ্তসার দেওয়া:

#include <signal.h>

using namespace std;

void terminate(int param)
/// Function executed if a segmentation fault is encountered during the cast to an instance.
{
  cerr << "\nThe function received a corrupted reference - please check the user-supplied  dll.\n";
  cerr << "Terminating program...\n";
  exit(1);
}

...
void MyFunction()
{
    void (*previous_sigsegv_function)(int);
    previous_sigsegv_function = signal(SIGSEGV, terminate);

    <-- insert risky stuff here -->

    signal(SIGSEGV, previous_sigsegv_function);
}

এখন এটি প্রত্যাশা মতো আচরণ করবে বলে মনে হচ্ছে (এটি ত্রুটির বার্তাটি প্রিন্ট করে, প্রোগ্রামটি সমাপ্ত করে) - তবে কেউ যদি কোনও ত্রুটি দেখাতে পারে তবে দয়া করে আমাকে জানান!


ব্যবহার করবেন না exit(), এটি আরআইআইকে অবরুদ্ধ করে এবং এর ফলে সংস্থানগুলি ফাঁস হতে পারে।
সেবাস্তিয়ান মাচ

আকর্ষণীয় - এই পরিস্থিতিতে ঝরঝরেভাবে শেষ করার অন্য কোনও উপায় আছে কি? এবং প্রস্থান বিবৃতিটি এ জাতীয় কাজটি করার ক্ষেত্রে একমাত্র সমস্যা? আমি লক্ষ্য করেছি যে আমি একটি "-1" অর্জন করেছি - এটি কেবল 'প্রস্থান' এর কারণে?
মাইক স্যাডলার

ওফস, আমি বুঝতে পারি এটি একটি দুর্দান্ত ব্যতিক্রমী পরিস্থিতির জন্য। আমি সবেমাত্র দেখেছি exit()এবং আমার পোর্টেবল সি ++ অ্যালার্ম বেল বাজতে শুরু করেছে। এই লিনাক্স নির্দিষ্ট পরিস্থিতিতে এটি ঠিক হওয়া উচিত, যেখানে আপনার প্রোগ্রামটি যে কোনও উপায়ে প্রস্থান করবে, আওয়াজের জন্য দুঃখিত sorry
সেবাস্তিয়ান মাচ

4
সংকেত (2) পোর্টেবল নয়। সিগিয়েশন (2) ব্যবহার করুন। man 2 signalলিনাক্সে একটি অনুচ্ছেদ রয়েছে যা ব্যাখ্যা করে।
rptb1

4
এই পরিস্থিতিতে আমি সাধারণত প্রস্থান (3) এর পরিবর্তে প্রস্থান (3) বলব কারণ এটি কোনও ধরণের ডিবাগিং ব্যাকট্রিস তৈরি করার সম্ভাবনা বেশি যা আপনি ময়না তদন্তের জন্য সমস্যাটি সনাক্ত করতে ব্যবহার করতে পারেন। বেশিরভাগ ইউনিক্সনে, অ্যাবোর্ট (3) কোর ডাম্প করবে (যদি কোর ডাম্পের অনুমতি দেওয়া হয়) এবং উইন্ডোজ এটি ইনস্টল করা থাকলে ডিবাগার চালু করার প্রস্তাব দেয়।
rptb1

2

সাধারণ ক্ষেত্রে হিসাবে পয়েন্টারের বৈধতার জন্য পরীক্ষা করার জন্য সি ++ তে কোনও বিধান নেই। স্পষ্টতই অনুমান করা যায় যে NULL (0x00000000) খারাপ, এবং বিভিন্ন সংকলক এবং গ্রন্থাগারগুলি ডিবাগিংকে আরও সহজ করতে এখানে এবং সেখানে "বিশেষ মানগুলি" ব্যবহার করতে পছন্দ করে (উদাহরণস্বরূপ, আমি যদি কখনও ভিজ্যুয়াল স্টুডিওতে 0xCECECECE হিসাবে পয়েন্টার দেখায় তবেই আমি জানি আমি কিছু ভুল করেছি) তবে সত্যটি হ'ল যেহেতু একটি পয়েন্টারটি মেমরির মধ্যে কেবল একটি সূচক তাই এটি "ডান" সূচকটি যদি পয়েন্টারটি দেখে কেবল বলা অসম্ভব।

ডায়নামিক_কাস্ট এবং আরটিটিআইয়ের সাথে আপনি করতে পারেন এমন বিভিন্ন কৌশল রয়েছে যাতে আপনি যে ধরণের জিনিসটি দেখতে চান তা সেই ধরণের হয় তা নিশ্চিত করার জন্য, তবে তাদের সবার প্রয়োজন যে আপনি প্রথম স্থানে বৈধ কিছুর দিকে নির্দেশ করছেন।

আপনি যদি নিশ্চিত করতে চান যে আপনি প্রোগ্রামটি "অবৈধ" পয়েন্টার সনাক্ত করতে পারে তবে আমার পরামর্শটি হ'ল: আপনি যেই পয়েন্টারটি NUL বা একটি বৈধ ঠিকানা হিসাবে ঘোষণা করেছেন তা তৈরি করার সাথে সাথে সেট করে সেটাকে মেমরিটি ইঙ্গিত করার পরে অবিলম্বে এটি NULL এ সেট করুন। আপনি যদি এই অনুশীলনটি সম্পর্কে কঠোর পরিশ্রমী হন, তবে NUL এর জন্য চেক করা আপনার যা প্রয়োজন তা-ই।


সি ++ (বা সি এর জন্য সি) একটি নাল পয়েন্টার, একটি ধ্রুবক অবিচ্ছেদ্য শূন্য দ্বারা প্রতিনিধিত্ব করা হয়। প্রচুর বাস্তবায়ন এটিকে উপস্থাপন করতে অল-বাইনারি-জিরো ব্যবহার করে তবে এটি নির্ভরযোগ্য কিছু নয়।
ডেভিড থর্নলি

2

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


2

ব্যবহারের আগে এবং পরে পয়েন্টারটি NULL এ সেট করা একটি ভাল কৌশল। উদাহরণস্বরূপ (একটি স্ট্রিং) কোনও শ্রেণীর মধ্যে পয়েন্টার পরিচালনা করলে এটি সি ++ এ করা সহজ:

class SomeClass
{
public:
    SomeClass();
    ~SomeClass();

    void SetText( const char *text);
    char *GetText() const { return MyText; }
    void Clear();

private:
    char * MyText;
};


SomeClass::SomeClass()
{
    MyText = NULL;
}


SomeClass::~SomeClass()
{
    Clear();
}

void SomeClass::Clear()
{
    if (MyText)
        free( MyText);

    MyText = NULL;
}



void SomeClass::Settext( const char *text)
{
    Clear();

    MyText = malloc( strlen(text));

    if (MyText)
        strcpy( MyText, text);
}

আপডেট হওয়া প্রশ্নটি অবশ্যই আমার উত্তরকে ভুল করে তোলে (অবশ্যই বা অন্য কোনও প্রশ্নের উত্তর অন্তত)। আমি উত্তরগুলির সাথে একমত যা মূলত বলে, তারা যদি এপিআই ব্যবহার করে তবে তাদের ক্র্যাশ করতে দিন। হাতুড়ি দিয়ে নিজেকে থাম্বতে আঘাত করা লোককে থামাতে পারবেন না ...
টিম রিং

2

পাবলিক এপিআইতে স্বেচ্ছাসেবক পয়েন্টারগুলিকে ইনপুট প্যারামিটার হিসাবে গ্রহণ করা খুব ভাল নীতি নয়। একটি পূর্ণসংখ্যা, স্ট্রিং বা স্ট্রাক্টের মতো "প্লেইন ডেটা" প্রকারের থাকা ভাল (এর অর্থ অভ্যন্তরে প্লেইন ডেটা সহ একটি ধ্রুপদী কাঠামো, অবশ্যই; আনুষ্ঠানিকভাবে কোনও কাঠামো হতে পারে)।

কেন? ঠিক আছে কারণ অন্যরা যেমন বলেছেন যে আপনাকে কোনও বৈধ পয়েন্টার দেওয়া হয়েছে বা জাঙ্কের দিকে ইঙ্গিত করে এমনটি জানার কোনও মানক উপায় নেই।

তবে কখনও কখনও আপনার পছন্দ হয় না - আপনার এপিআই অবশ্যই পয়েন্টার গ্রহণ করবে।

এই ক্ষেত্রে, ভাল পয়েন্টার পাস করা কলারের কর্তব্য। NULL মান হিসাবে গৃহীত হতে পারে তবে জাঙ্কের কোনও পয়েন্টার নয়।

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

// API that does not allow NULL
void PublicApiFunction1(Person* in_person)
{
  assert(in_person != NULL);
  assert(in_person->Invariant());

  // Actual code...
}

// API that allows NULL
void PublicApiFunction2(Person* in_person)
{
  assert(in_person == NULL || in_person->Invariant());

  // Actual code (must keep in mind that in_person may be NULL)
}

পুনরায়: "একটি স্ট্রিনের মতো একটি সরল ডেটা টাইপ পাস করুন" তবে সি ++ স্ট্রিংগুলিতে প্রায়শই অক্ষরগুলিতে পয়েন্টার হিসাবে (চার *) বা (কনস্ট চার *) পাস করা হয়, সুতরাং আপনি পয়েন্টারগুলি পাসিংয়ে ফিরে এসেছেন। এবং আপনার উদাহরণটি ইন-প্রেসারকে রেফারেন্স হিসাবে পাস করেছে, পয়েন্টার হিসাবে নয়, সুতরাং তুলনাটি (in_Press! = NULL) বোঝায় কিছু ব্যক্তি / পয়েন্টার তুলনা ব্যক্তি শ্রেণিতে সংজ্ঞায়িত হয়।
জেসি চিশল্ম

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

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

1

অন্যরা যেমন বলেছে, আপনি নির্ভরযোগ্যভাবে কোনও অবৈধ পয়েন্টার সনাক্ত করতে পারবেন না। একটি অবৈধ পয়েন্টার নিতে পারে এমন কিছু ফর্ম বিবেচনা করুন:

আপনি একটি নাল পয়েন্টার থাকতে পারে। এটি এমন একটি যা আপনি সহজেই পরীক্ষা করতে পারেন এবং এ সম্পর্কে কিছু করতে পারেন।

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

আপনার বৈধ মেমরির ভিতরে এমনকি কোথাও আপনার পয়েন্টার থাকতে পারে এমনকি আপনার ডেটা বিভাগ, বিএসএস, স্ট্যাক বা হ্যাপের ভিতরেও, তবে কোনও বৈধ অবজেক্টের দিকে নির্দেশ না করে। এর বৈকল্পিক হ'ল একটি পয়েন্টার যা কোনও বৈধ অবজেক্টের দিকে নির্দেশ করতে ব্যবহৃত হত, বস্তুর সাথে খারাপ কিছু হওয়ার আগে। এই প্রসঙ্গে খারাপ জিনিসগুলির মধ্যে হ্রাস, স্মৃতি দুর্নীতি বা পয়েন্টার দুর্নীতি অন্তর্ভুক্ত।

আপনার কাছে ফ্ল্যাট-আউট অবৈধ পয়েন্টার থাকতে পারে, যেমন জিনিসটির রেফারেন্স হওয়ার জন্য অবৈধ প্রান্তিককরণ সহ একটি পয়েন্টার।

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

আপনি যা করতে পারেন তা হ'ল ক্র্যাশটিকে অনুমতি দেওয়া এবং কিছু ভাল ডায়াগোনস্টিক তথ্য দেওয়া।


পুনরায়: "কিছু ভাল ডায়গনিস্টিক তথ্য রাখুন", ঘষা আছে। যেহেতু আপনি পয়েন্টার বৈধতার জন্য যাচাই করতে পারবেন না, তাই আপনার যে তথ্যগুলি নিয়ে ঝাঁকুনির দরকার তা ন্যূনতম। "এখানে একটি ব্যতিক্রম ঘটেছে," আপনি যা পেতে পারেন তা হতে পারে। পুরো কল স্ট্যাকটি দুর্দান্ত, তবে বেশিরভাগ সি ++ রান টাইম লাইব্রেরি সরবরাহের চেয়ে আরও ভাল ফ্রেমওয়ার্ক প্রয়োজন।
জেসি চিশল্ম


1

সাধারণভাবে, এটি করা অসম্ভব। এখানে একটি বিশেষভাবে বাজে মামলা:

struct Point2d {
    int x;
    int y;
};

struct Point3d {
    int x;
    int y;
    int z;
};

void dump(Point3 *p)
{
    printf("[%d %d %d]\n", p->x, p->y, p->z);
}

Point2d points[2] = { {0, 1}, {2, 3} };
Point3d *p3 = reinterpret_cast<Point3d *>(&points[0]);
dump(p3);

অনেক প্ল্যাটফর্মে, এটি মুদ্রণ করবে:

[0 1 2]

আপনি রানটাইম সিস্টেমকে মেমরির বিটের ভুল ব্যাখ্যা করতে বাধ্য করছেন, তবে এই ক্ষেত্রে এটি ক্রাশ হচ্ছে না, কারণ বিটগুলি সমস্ত বোঝায়। এই (সঙ্গে সি-শৈলী পলিমরফিজম এ বর্ণন ভাষা নকশা অংশ struct inaddr, inaddr_in, inaddr_in6,) যাতে আপনি নির্ভরযোগ্যভাবে যে কোনও প্ল্যাটফর্ম তে এটি রক্ষা করতে পারবে না।


1

আপনি উপরের নিবন্ধগুলিতে কত বিভ্রান্তিকর তথ্য পড়তে পারবেন তা অবিশ্বাস্য ...

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

গুগল করে আমি উইন্ডোজের জন্য কোনও কার্যকর উদাহরণ খুঁজে পাইনি - 32-বিট অ্যাপসের সমাধান পেয়েছি,

http://www.codeproject.com/script/Content/ViewAssociatedFile.aspx?rzp=%2FKB%2Fsystem%2Fdetect-driver%2F%2FDtetectDriverSrc.zip&zep=DedctDriverSrc%2FDteteddrc%%fdccrt%crtcrr%%fdtcrrt%crtcrc… = 2

তবে আমার 64৪-বিট অ্যাপ্লিকেশনগুলি সমর্থন করাও দরকার, সুতরাং এই সমাধানটি আমার পক্ষে কার্যকর হয়নি।

তবে আমি ওয়াইনের উত্স কোডগুলি সংগ্রহ করেছি এবং একই ধরণের কোড রান্না করতে পেরেছি যা 64৪-বিট অ্যাপ্লিকেশনগুলির জন্যও কাজ করবে - কোড সংযুক্তি এখানে:

#include <typeinfo.h>   

typedef void (*v_table_ptr)();   

typedef struct _cpp_object   
{   
    v_table_ptr*    vtable;   
} cpp_object;   



#ifndef _WIN64
typedef struct _rtti_object_locator
{
    unsigned int signature;
    int base_class_offset;
    unsigned int flags;
    const type_info *type_descriptor;
    //const rtti_object_hierarchy *type_hierarchy;
} rtti_object_locator;
#else

typedef struct
{
    unsigned int signature;
    int base_class_offset;
    unsigned int flags;
    unsigned int type_descriptor;
    unsigned int type_hierarchy;
    unsigned int object_locator;
} rtti_object_locator;  

#endif

/* Get type info from an object (internal) */  
static const rtti_object_locator* RTTI_GetObjectLocator(void* inptr)  
{   
    cpp_object* cppobj = (cpp_object*) inptr;  
    const rtti_object_locator* obj_locator = 0;   

    if (!IsBadReadPtr(cppobj, sizeof(void*)) &&   
        !IsBadReadPtr(cppobj->vtable - 1, sizeof(void*)) &&   
        !IsBadReadPtr((void*)cppobj->vtable[-1], sizeof(rtti_object_locator)))  
    {  
        obj_locator = (rtti_object_locator*) cppobj->vtable[-1];  
    }  

    return obj_locator;  
}  

এবং নিম্নলিখিত কোডটি পয়েন্টারটি বৈধ আছে কি না তা সনাক্ত করতে পারে, আপনার সম্ভবত কিছু NUL চেকিং যুক্ত করা দরকার:

    CTest* t = new CTest();
    //t = (CTest*) 0;
    //t = (CTest*) 0x12345678;

    const rtti_object_locator* ptr = RTTI_GetObjectLocator(t);  

#ifdef _WIN64
    char *base = ptr->signature == 0 ? (char*)RtlPcToFileHeader((void*)ptr, (void**)&base) : (char*)ptr - ptr->object_locator;
    const type_info *td = (const type_info*)(base + ptr->type_descriptor);
#else
    const type_info *td = ptr->type_descriptor;
#endif
    const char* n =td->name();

এটি পয়েন্টার থেকে শ্রেণীর নাম পেয়েছে - আমি মনে করি এটি আপনার প্রয়োজনের জন্য যথেষ্ট হওয়া উচিত।

একটি জিনিস যা আমি এখনও ভয় পাচ্ছি সেটি হল পয়েন্টার চেকিংয়ের পারফরম্যান্স - উপরে কোড স্নিপেটে ইতিমধ্যে 3-4 টি এপিআই কল করা হচ্ছে - সমালোচনামূলক অ্যাপ্লিকেশনগুলির জন্য ওভারকিল হতে পারে।

যদি কেউ সি # / পরিচালিত সি ++ কলগুলির সাথে তুলনা করে পয়েন্টার চেকিংয়ের ওভারহেড পরিমাপ করতে পারে তবে এটি ভাল good


1

প্রকৃতপক্ষে, নির্দিষ্ট অনুষ্ঠানের অধীনে কিছু করা যেতে পারে: উদাহরণস্বরূপ, আপনি যদি স্ট্রিং পয়েন্টার স্ট্রিংটি বৈধ কিনা তা পরীক্ষা করতে চান, লেখার (এফডি, বুফ, এসজি) সিস্কেল ব্যবহার করে আপনাকে যাদু করতে সহায়তা করতে পারে: fd অস্থায়ী ফাইলের বিবরণী হতে দিন আপনি পরীক্ষার জন্য যে ফাইলটি তৈরি করেছেন এবং বুফটি আপনি টেস্টিংয়ের স্ট্রিংয়ের দিকে ইঙ্গিত করছেন, যদি পয়েন্টারটি অবৈধ থাকে তবে লিখিত (1) ফিরে আসবে এবং EFULT এ সেট হবে যা নির্দেশ করে যে বুফ আপনার অ্যাক্সেসযোগ্য ঠিকানার জায়গার বাইরে রয়েছে।


1

উইন্ডোতে নিম্নলিখিতটি কাজ করে (এটি আগে কেউ প্রস্তাব করেছিল):

 static void copy(void * target, const void* source, int size)
 {
     __try
     {
         CopyMemory(target, source, size);
     }
     __except(EXCEPTION_EXECUTE_HANDLER)
     {
         doSomething(--whatever--);
     }
 }

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


1

উইন্ডোজে আমি এই কোডটি ব্যবহার করি:

void * G_pPointer = NULL;
const char * G_szPointerName = NULL;
void CheckPointerIternal()
{
    char cTest = *((char *)G_pPointer);
}
bool CheckPointerIternalExt()
{
    bool bRet = false;

    __try
    {
        CheckPointerIternal();
        bRet = true;
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
    }

    return  bRet;
}
void CheckPointer(void * A_pPointer, const char * A_szPointerName)
{
    G_pPointer = A_pPointer;
    G_szPointerName = A_szPointerName;
    if (!CheckPointerIternalExt())
        throw std::runtime_error("Invalid pointer " + std::string(G_szPointerName) + "!");
}

ব্যবহার:

unsigned long * pTest = (unsigned long *) 0x12345;
CheckPointer(pTest, "pTest"); //throws exception

0

উইন্ডোজের জন্য ইসব্যাডআরডিপিআরটি (), ইসব্যাডওরাইটপ্রিটার (), ইসব্যাডকোডপ্রিটার (), ইসব্যাডস্ট্রিংপিআরটি ()।
এগুলি ব্লকের দৈর্ঘ্যের সাথে সমানুপাতিক সময় নেয়, তাই স্যানিটি পরীক্ষার জন্য আমি কেবল প্রারম্ভিক ঠিকানাটি যাচাই করি।


4
আপনার এই পদ্ধতিগুলি এড়ানো উচিত কারণ তারা কাজ করে না। ব্লগস.এমএসডিএন
ওল্ডনেউথিং /

: কখনও কখনও তাদের কাছে তাদের কাজ করছে না-এরাউন্ড হতে পারে stackoverflow.com/questions/496034/...
ChrisW

0

আমি দেখেছি বিভিন্ন লাইব্রেরি অযৌক্তিক মেমরির পরীক্ষা করার জন্য কিছু পদ্ধতি ব্যবহার করে এবং এ জাতীয়। আমি বিশ্বাস করি তারা কেবল মেমরি বরাদ্দ এবং deallocation পদ্ধতি (malloc / ফ্রি) "ওভাররাইড" করে, যার কিছু যুক্তি যা পয়েন্টারগুলি ট্র্যাক করে রাখে। আমি মনে করি এটি আপনার ব্যবহারের ক্ষেত্রে অত্যধিক দক্ষ, তবে এটি করার এক উপায় এটি হবে।


দুর্ভাগ্যক্রমে, স্ট্যাক-বরাদ্দ বস্তুগুলির জন্য এটি সহায়তা করে না।
টম

0

প্রযুক্তিগতভাবে আপনি অপারেটরটিকে নতুন (এবং মুছে ফেলুন ) ওভাররাইড করতে পারেন এবং সমস্ত বরাদ্দ মেমরির তথ্য সংগ্রহ করতে পারেন, যাতে হিপ মেমরিটি বৈধ কিনা তা পরীক্ষা করার জন্য আপনার একটি পদ্ধতি থাকতে পারে। তবে:

  1. আপনার এখনও স্ট্যাকের মধ্যে পয়েন্টার বরাদ্দ করা হয়েছে কিনা তা পরীক্ষা করার একটি উপায় প্রয়োজন ()

  2. আপনাকে 'বৈধ' পয়েন্টার কী তা নির্ধারণ করতে হবে:

ক) এই ঠিকানায় মেমরি বরাদ্দ করা হয়

খ) সেই ঠিকানায় মেমরি শুরু হয় বস্তুর ঠিকানা (বিশাল অ্যারের মাঝখানে না ঠিকানা যেমন)

গ) সেই ঠিকানায় মেমরিটি প্রত্যাশিত অবজেক্টের সূচনা ঠিকানা ধরণের

নীচের লাইন : প্রশ্নে পদ্ধতিটি সি ++ উপায় নয়, আপনাকে কিছু নিয়ম সংজ্ঞায়িত করতে হবে যা নিশ্চিত করে যে ফাংশনটি বৈধ পয়েন্টার গ্রহণ করে।


0

সি ++ এ চেক করার কোনও উপায় নেই। যদি অন্য কোড আপনাকে একটি অবৈধ পয়েন্টারটি দেয় তবে আপনার কী করা উচিত? তোমার ক্রাশ হওয়া উচিত কেন? এই লিঙ্কটি দেখুন: http://blogs.msdn.com/oldnewthing/archive/2006/09/27/773741.aspx


0

অভিযুক্ত উত্তর (গুলি) এ সংযোজন:

ধরে নিন যে আপনার পয়েন্টারটিতে কেবলমাত্র তিনটি মান থাকতে পারে - 0, 1 এবং -1 যেখানে 1 বৈধ পয়েন্টার হিসাবে চিহ্নিত করে, -1 একটি অবৈধ এবং অন্য 0 টি অবৈধ। সম্ভাব্যতা যে আপনার পয়েন্টার কি হয় নাল, সব মান সমান সম্ভাবনা হচ্ছে? ১/৩। এখন, বৈধ কেসটি বাইরে নিয়ে আসুন, সুতরাং প্রতিটি অবৈধ মামলার জন্য, সমস্ত ত্রুটি ধরার জন্য আপনার কাছে 50:50 অনুপাত রয়েছে। ভাল লাগছে তো? এটি 4-বাইট পয়েন্টারের জন্য স্কেল করুন। 2 ^ 32 বা 4294967294 সম্ভাব্য মান রয়েছে। এর মধ্যে কেবল একটি মানই সঠিক, একটি হ'ল নুল, এবং এখনও আপনার অবধি 4294967292 অন্যান্য অবৈধ মামলা রয়েছে। পুনরায় গণনা: আপনার অবৈধ মামলার (4294967292+ 1) এর মধ্যে 1 টির পরীক্ষা রয়েছে a বেশিরভাগ ব্যবহারিক উদ্দেশ্যে 2.xe-10 বা 0 এর সম্ভাবনা। এ জাতীয় NUL চেক এর নিরর্থকতা।


0

আপনি জানেন, একটি নতুন ড্রাইভার (এটি অন্তত লিনাক্সে) সক্ষম যা সম্ভবত এটি লিখতে অসুবিধা হবে না।

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


0

আপনার এই পদ্ধতিগুলি এড়ানো উচিত কারণ তারা কাজ করে না। ব্লগস.এমএসডিএন / ওল্ডনেউথিং / অর্কিভ / ২০০/0/০৯/27/773741.aspx - জারেডপাড় 15 ফেব্রুয়ারী '09 এ 16:02 এ

যদি তারা কাজ না করে - পরবর্তী উইন্ডোজ আপডেট এটি ঠিক করে দেবে? যদি তারা ধারণা স্তরে কাজ না করে - ফাংশন সম্ভবত উইন্ডোজ এপিআই থেকে সম্পূর্ণভাবে মুছে ফেলা হবে।

এমএসডিএন ডকুমেন্টেশন দাবি করে যে এগুলি নিষিদ্ধ করা হয়েছে এবং এর কারণ সম্ভবত অ্যাপ্লিকেশনটির আরও নকশার ত্রুটি (উদাহরণস্বরূপ আপনি নিঃশব্দে অবৈধ পয়েন্টার খাওয়া উচিত নয় - যদি আপনি অবশ্যই পুরো প্রয়োগের নকশার দায়িত্বে থাকেন), এবং কার্য সম্পাদন / সময় পয়েন্টার চেকিং।

তবে আপনার দাবি করা উচিত নয় যে তারা কিছু ব্লগের কারণে কাজ করে না। আমার পরীক্ষার প্রয়োগে আমি যাচাই করেছি যে তারা কাজ করে।


0

এই লিঙ্কগুলি সহায়ক হতে পারে

_সিআরটিআইএসভিডিলপয়েন্টার যাচাই করে যে একটি নির্দিষ্ট মেমরির পরিসর পড়া এবং লেখার জন্য বৈধ (কেবলমাত্র ডিবাগ সংস্করণ)। http://msdn.microsoft.com/en-us/library/0w1ekd5e.aspx

_CrtCheckMemory ডিবাগ হিপ (কেবলমাত্র ডিবাগ সংস্করণ) এ বরাদ্দ হওয়া মেমরি ব্লকের অখণ্ডতার নিশ্চয়তা দেয়। http://msdn.microsoft.com/en-us/library/e73x0s4b.aspx

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.