কোনও নাল উদাহরণে কোনও সদস্য ফাংশন প্রার্থনা করলে অনির্ধারিত আচরণের ফলাফল হয়?


120

নিম্নলিখিত কোড বিবেচনা করুন:

#include <iostream>

struct foo
{
    // (a):
    void bar() { std::cout << "gman was here" << std::endl; }

    // (b):
    void baz() { x = 5; }

    int x;
};

int main()
{
    foo* f = 0;

    f->bar(); // (a)
    f->baz(); // (b)
}

আমরা (b)ক্রাশের প্রত্যাশা করব , কারণ xনাল পয়েন্টারের জন্য কোনও সংশ্লিষ্ট সদস্য নেই । অনুশীলনে, (a)ক্রাশ হয় না কারণ thisপয়েন্টারটি কখনই ব্যবহৃত হয় না।

কারণ পয়েন্টারটিকে ( ) (b)অবজ্ঞা করে এবং নাল হয়, প্রোগ্রামটি অনির্ধারিত আচরণে প্রবেশ করে, কারণ নালকে সর্বদা অবধারিত আচরণ বলে।this(*this).x = 5;this

অপরিবর্তিত (a)আচরণের ফলে কি ঘটে? উভয় ফাংশন (এবং x) স্থির থাকলে কী হবে?


যদি উভয় ফাংশন স্থিতিশীল হয় তবে এক্সকে বাজের অভ্যন্তরে কীভাবে উল্লেখ করা যেতে পারে ? (এক্স একটি স্থির সদস্যের পরিবর্তনশীল)
কিংবদন্তি

4
@ কিংবদন্তি 2 কে: ভান করাও অচল xছিল। :)
GManNickG

অবশ্যই, তবে মামলার (ক) ক্ষেত্রে এটি একই ক্ষেত্রে কাজ করে, অর্থাত্ ফাংশনটি আহ্বান জানায়। যাইহোক, পয়েন্টারের মান 0 থেকে 1 এর পরিবর্তে (বলুন, পুনরায় ব্যাখ্যা_কাস্টের মাধ্যমে), এটি প্রায় সর্বদা সর্বদা ক্রাশ হয়। 0 এর মান বরাদ্দ এবং এভাবে NULL, যেমন ক হিসাবে, সংকলকটির জন্য বিশেষ কিছু উপস্থাপন করে? এটি কেন বরাদ্দ করা অন্য কোনও মান সহ সর্বদা ক্রাশ হয়?
সিদ্ধার্থ শঙ্করন

5
আকর্ষণীয়: আসুন সি ++ এর পরবর্তী সংশোধন, পয়েন্টারগুলির আর কোনও ডিটারফারেন্সিং হবে না। আমরা এখন পয়েন্টারগুলির মাধ্যমে ইন্ডিয়ারেশন সম্পাদন করব। আরও জানতে, দয়া করে এই লিঙ্কটির মাধ্যমে ইন্ডিয়ারেশন
জেমস ম্যাকনেলিস

3
নাল পয়েন্টারে সদস্য ফাংশনটি চালানো সর্বদা সংজ্ঞায়িত আচরণ। কেবল আপনার কোডটি দেখে, আমি ইতিমধ্যে অনির্ধারিত আচরণটি ধীরে ধীরে আমার ঘাড়ে ক্রল করতে পারছি!
ফ্রেডওভারফ্লো

উত্তর:


113

উভয় (a)এবং (b)অনির্ধারিত আচরণের ফলাফল। নাল পয়েন্টারের মাধ্যমে সদস্য ফাংশনটিতে কল করা সর্বদা অপরিবর্তিত আচরণ। যদি ফাংশনটি স্থিতিশীল হয় তবে এটি প্রযুক্তিগতভাবেও অপরিবর্তিত, তবে কিছু বিবাদ রয়েছে।


প্রথমে বুঝতে হবে এটি কেন নাল পয়েন্টারকে অবজ্ঞা করার জন্য এটি অপরিবর্তিত আচরণ। C ++ 03 এ আসলে এখানে কিছুটা অস্পষ্টতা রয়েছে।

যদিও " অপরিজ্ঞাত আচরণে নাল পয়েন্টার ফলাফলকে ডিফারেন্সিং করা " §1.9 / 4 এবং .38.3.2 / 4 উভয়ই নোটগুলিতে উল্লেখ করা হয়েছে, এটি কখনই স্পষ্টভাবে বলা হয়নি। (নোটগুলি মানহানিকর are

তবে, কেউ এটিকে §3.10 / 2 থেকে বাদ দেওয়ার চেষ্টা করতে পারেন:

একটি ল্যাভেলু একটি অবজেক্ট বা ফাংশনকে বোঝায়।

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

নির্বিশেষে, এটি অবশ্যই কোনও মূলকে (.14.1 / 1) রূপান্তর করা যাবে না:

যদি লভ্যালুটি অবজেক্টটি বোঝায় তবে এটি টাইপ টি-এর একটি অবজেক্ট নয় এবং টি থেকে প্রাপ্ত কোনও ধরণের অবজেক্ট নয় বা যদি অবজেক্টটি অনির্বাচিত করা হয়, এমন একটি প্রোগ্রাম যা এই রূপান্তরটির প্রয়োজন হয় তার অপরিজ্ঞাত আচরণ রয়েছে।

এখানে এটি অবশ্যই সংজ্ঞায়িত আচরণ।

অস্পষ্টতাটি শ্রদ্ধার সাথে অনির্ধারিত আচরণ করা বা না হওয়া থেকে অবৈধ পয়েন্টার থেকে মানটি ব্যবহার না করা থেকে আসে (অর্থাত্ একটি মূল্যমান পান তবে এটি কোনও মূল্যকে রূপান্তর করবেন না)। যদি না হয়, তবে int *i = 0; *i; &(*i);ভালভাবে সংজ্ঞায়িত করা হয়েছে। এটি একটি সক্রিয় সমস্যা

সুতরাং আমাদের কঠোরভাবে "নাল পয়েন্টারকে অবজ্ঞা করা, সংজ্ঞায়িত আচরণ" দৃষ্টিভঙ্গি পাওয়া এবং দুর্বল "একটি অবজ্ঞাপিত নাল পয়েন্টার ব্যবহার করুন, অপরিজ্ঞাত আচরণ করুন" দেখুন।

এখন আমরা প্রশ্ন বিবেচনা।


হ্যাঁ, (a)অনির্ধারিত আচরণের ফলাফল। আসলে, যদি thisনাল হয় তবে ফাংশনের বিষয়বস্তু নির্বিশেষে ফলাফল নির্ধারিত হয়।

এটি §5.2.5 / 3 থেকে অনুসরণ করে:

যদি E1"দশম শ্রেণিতে পয়েন্টার" টাইপ থাকে তবে এক্সপ্রেশনটি E1->E2সমমানের ফর্মে রূপান্তরিত হয়(*(E1)).E2;

*(E1)একটি কঠোর ব্যাখ্যার সাথে অনির্ধারিত আচরণের ফলাফল .E2ঘটবে এবং এটিকে একটি মূলকে রূপান্তরিত করে দুর্বল ব্যাখ্যার জন্য এটি অনির্ধারিত আচরণ করে।

এটি অনুসরণ করে যে এটি সরাসরি (ined9.3.1 / 1) থেকে অপরিবর্তিত আচরণ:

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


স্ট্যাটিক ফাংশন সহ, কঠোর বনাম দুর্বল ব্যাখ্যা পার্থক্য করে। কড়া কথা বলতে গেলে এটি অপরিজ্ঞাত:

স্থির সদস্যকে ক্লাস সদস্য অ্যাক্সেস সিনট্যাক্স ব্যবহার করে উল্লেখ করা যেতে পারে, যার ক্ষেত্রে অবজেক্ট-এক্সপ্রেশনকে মূল্যায়ন করা হয়।

এটি হ'ল এটির মূল্যায়ন ঠিক এমনভাবে হয় যেন এটি অ স্থির ছিল এবং আমরা আবারও একটি নাল পয়েন্টারকে অবজ্ঞার সাথে দেখি (*(E1)).E2

তবে E1স্থির সদস্য-ফাংশন কলটিতে ব্যবহৃত না হওয়ায় আমরা যদি দুর্বল ব্যাখ্যাটি ব্যবহার করি তবে কলটি সঠিকভাবে সংজ্ঞায়িত। *(E1)ফলস্বরূপ একটি ফলমূল হয়, স্থির ফাংশনটি সমাধান করা হয়, *(E1)বাতিল করা হয় এবং ফাংশনটি বলা হয়। কোনও মূল্যমানের থেকে মূল্যমান রূপান্তর নেই, তাই কোনও সংজ্ঞায়িত আচরণ নেই।

সি ++ 0 এক্সে, এন 3126 অনুসারে, অস্পষ্টতা রয়ে গেছে। আপাতত, নিরাপদ থাকুন: কঠোর ব্যাখ্যাটি ব্যবহার করুন।


5
+1 টি। পেডেন্ট্রি চালিয়ে যাওয়া, "দুর্বল সংজ্ঞা" এর অধীনে ননস্ট্যাটিক সদস্য ফাংশনটি "এমন কোনও বস্তুর জন্য যা এক্স টাইপের নয়" জন্য ডাকা হয় নি। এটি এমন একটি মূল্যমানের জন্য বলা হয়েছে যা কোনও বস্তু নয়। সুতরাং প্রস্তাবিত সমাধানটি "আপনি বা ক্লাবটি যদি খালি লভ্যালু হয়" তবে আপনার উদ্ধৃতিটি প্রবন্ধটি যুক্ত করে।
স্টিভ জেসোপ

আপনি একটু স্পষ্ট করতে পারেন? বিশেষত, আপনার "বদ্ধ ইস্যু" এবং "সক্রিয় ইস্যু" লিঙ্কগুলির সাথে ইস্যু সংখ্যাগুলি কী? এছাড়াও, যদি এটি একটি বন্ধ সমস্যা হয় তবে স্থির ক্রিয়াকলাপগুলির জন্য হ্যাঁ / কোন উত্তরটি ঠিক কী? আমি আপনার উত্তরটি বোঝার চূড়ান্ত পদক্ষেপটি মিস করছি বলে মনে হচ্ছে feel
ব্রুকস মুসা

4
আমি মনে করি না যে "বদ্ধ সমস্যাগুলি" পৃষ্ঠাতে উপস্থিত থাকার ফলে সিডাব্লুজি 316 ত্রুটিটি "বন্ধ" হিসাবে রয়েছে। যুক্তিটি বলে যে এটির অনুমতি দেওয়া উচিত কারণ " যদি নালাগুলি মূল্যহীন রূপে রূপান্তর না করা হয় তবে " *pত্রুটি নয় p"" যাইহোক, এটি একটি "খালি লভ্যালু" ধারণার উপর নির্ভর করে যা সিডাব্লুজি ত্রুটির 232 এর প্রস্তাবিত রেজোলিউশনের অংশ , তবে এটি গৃহীত হয়নি। সুতরাং, C ++ 03 এবং C ++ 0x উভয় ভাষাতেই নাল পয়েন্টারটিকে ডিফারেন্স করা এখনও অবধারিত নয়, এমনকি যদি কোনও মূল্য-থেকে-অবধি রূপান্তর না হয়।
জেমস ম্যাকনেলিস

1
@ জেমস এমসিএনেলিস: আমার বোঝার দ্বারা, যদি pএমন একটি হার্ডওয়্যার ঠিকানা হয় যা পড়ার সময় কিছু ক্রিয়াকলাপ ঘটায় , তবে ঘোষিত না হয় volatile, বিবৃতিটির *p;প্রয়োজন হবে না, তবে সেই ঠিকানাটি পড়ার অনুমতি দেওয়া হবে ; বিবৃতি &(*p);, যদিও এটি করতে নিষেধ করা হবে। যদি *pহয় volatile, পড়ার প্রয়োজন হবে। উভয় ক্ষেত্রেই, যদি পয়েন্টারটি অবৈধ হয়, তবে আমি দেখতে পাচ্ছি না যে প্রথম বিবৃতিটি অপরিজ্ঞাত আচরণ নয়, তবে দ্বিতীয় বিবৃতি কেন হবে তাও আমি দেখতে পাচ্ছি না।
ক্যাট

1
".E2 এটিকে একটি মূলকে রূপান্তরিত করে," - উহ, না এটি হয় না
এমএম

30

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

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

মাইক্রোসফ্টের এমএফসি ফাংশন গেটসএফএইচএনডি আসলে এই আচরণের উপর নির্ভর করে। আমি জানি না তারা কী ধূমপান করছিল।

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


1
GetSafeHwnd প্রথমে একটি করে! এই চেকটি করে এবং যদি সত্য হয়, NULL প্রদান করে। তারপরে এটি একটি এসইএইচ ফ্রেম শুরু করে এবং পয়েন্টারটিকে অবহেলা করে। যদি মেমোরি অ্যাক্সেস লঙ্ঘন হয় (0xc0000005) তবে এটি ধরা পড়ে এবং NULL কলারে ফিরে আসে :) অন্যথায় এইচডব্লিউএনডি ফিরে আসে।
Петров

@ ПетърПетров কোডটির দিকে নজর দেওয়ার পরে বেশ কয়েক বছর হয়ে গেছে GetSafeHwnd, সম্ভবত তারা তখন থেকেই এটি বাড়িয়ে নিয়েছে। এবং ভুলে যাবেন না যে তারা সংকলক কার্যক্রমে অভ্যন্তরীণ জ্ঞান আছে!
মার্ক

আমি একটি নমুনা সম্ভাব্য প্রয়োগের কথা বলছি যা একই প্রভাব ফেলবে, এটি আসলে কী করে তা হ'ল
ডিবাগারটি

1
"তাদের সংকলক কার্যক্রমে অভ্যন্তরীণ জ্ঞান আছে!" - MinGW এর মতো প্রকল্পগুলির চিরন্তন সমস্যার কারণ যা ++ কে উইন্ডোজ এপিআই বলে যে কোডটি সংকলন করার অনুমতি দেওয়ার চেষ্টা করে
এমএম

@ এমএম আমি মনে করি আমরা সকলেই সম্মতি জানাই এটি অন্যায্য। এবং সে কারণে, আমি এটিও মনে করি যে সামঞ্জস্যতা সম্পর্কে একটি আইন রয়েছে যা এটি এটি রাখা একটি সামান্য বিট অবৈধ করে তোলে।
v.oddou
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.