সি ++ ফাংশন কোনও নির্দিষ্ট ভেরিয়েবলের মান পরিবর্তন করবে কিনা তা নির্ধারণ করতে পারে এমন একটি সংকলক তৈরি করা কেন অসম্ভব?


104

আমি এই বইটি একটি বইতে পড়েছি:

এমন একটি সংকলক তৈরি করা অসম্ভব যেটি আসলে একটি সি ++ ফাংশন নির্দিষ্ট ভেরিয়েবলের মান পরিবর্তন করবে কিনা তা নির্ধারণ করতে পারে।

অনুচ্ছেদটি কনস্ট-নেসের জন্য পরীক্ষা করার সময় সংকলক কেন রক্ষণশীল তা নিয়ে কথা বলছিল।

কেন এমন সংকলক তৈরি করা অসম্ভব?

সংকলক সর্বদা এটি পরীক্ষা করতে পারে যে কোনও পরিবর্তনশীল পুনরায় নিয়োগ দেওয়া হয়েছে কিনা, এটিতে একটি অ-কনস্ট্যান্ট ফাংশন চাওয়া হচ্ছে, বা যদি এটি একটি অ-কনস্ট্যান্ট প্যারামিটার হিসাবে পাস করা হচ্ছে ...


24
আমার মনে প্রথম যে বিষয়টি আসে তা হ'ল ডায়নামিক লিঙ্ক লাইব্রেরি। আমি যদি আমার মেশিনে কোডটি সংকলন করি এবং আপনি আপনার মেশিনে কোডটি সংকলন করেন এবং রান চলাকালীন আমরা সেগুলি লিঙ্ক করি , আমি কী পরিবর্তন করতে পারি বা কীভাবে আপনার সংকলকটি কীভাবে জানতে পারবেন?
মাকিং হাঁস

4
নিখুঁতভাবে আরও বিস্তৃতভাবে, সংকলক পৃথকভাবে ফাংশনটি সংকলন করে না, তবে এটি একটি বিস্তৃত চিত্রের অংশ হিসাবে সংকলন করে যা সমস্তই সংকলকের স্কোপের মধ্যে নাও থাকতে পারে।
called2voyage

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

36
@ টাটবার্গ ইম্পসিবল কোনও অতিরিক্ত কাজ নয়, বেশ কয়েকটি উত্তর ব্যাখ্যা করার সাথে সাথে এখানে হাল্টিং সমস্যাটি প্রযোজ্য। সাধারণ প্রোগ্রামকে সম্পূর্ণভাবে অ্যালগরিদম বিশ্লেষণ করা সম্ভব নয়।
ফিক্টিক

5
@ টিওয়ালবার্গ সংকলকগুলি যা কেবলমাত্র বৈধ প্রোগ্রামগুলির একটি উপসেট সংকলন করে খুব কার্যকর নয়।
কালেব

উত্তর:


139

কেন এমন সংকলক তৈরি করা অসম্ভব?

একই কারণে আপনি কোনও প্রোগ্রাম লিখতে পারবেন না যা নির্ধারণ করবে যে কোনও প্রদত্ত প্রোগ্রাম শেষ হবে কিনা। এটি হোল্টিং সমস্যা হিসাবে পরিচিত এবং এটি গণনাযোগ্য নয় এমন একটি বিষয়।

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

এখানে একটি সহজ উদাহরণ:

void foo() {
    if (bar() == 0) this->a = 1;
}

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


48
@ মিস্ট্রোল্টিস, কিছু সমস্যার জন্য কোয়ান্টাম কম্পিউটারগুলি কেবল "কেবল" দ্রুত, তারা অনস্বীকার্য সমস্যা সমাধান করতে পারে না।
zch

8
@ এমরোসটলিস যেসব তাত্পর্যপূর্ণ জটিল অ্যালগরিদমগুলি (ফ্যাক্টরিংয়ের মতো) কোয়ান্টাম কম্পিউটারগুলির জন্য উপযুক্ত, তবে থামানো সমস্যাটি একটি যৌক্তিক দ্বিধা, আপনার কী ধরণের "কম্পিউটার" রয়েছে তা বিবেচনাযোগ্য নয়।
ব্যবহারকারী 1032613

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

9
@ থরবজরন রাভানএন্ডারসেন: ঠিক আছে, সুতরাং, ধরুন আমি কোনও প্রোগ্রাম চালাচ্ছি। এটি সমাপ্ত হবে কিনা আমি ঠিক কীভাবে নির্ধারণ করব?
রুখ

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

124

কল্পনা করুন যেমন সংকলক বিদ্যমান। আসুন ধরে নেওয়া যাক সুবিধার জন্য এটি একটি লাইব্রেরি ফাংশন সরবরাহ করে যা 1 প্রদান করে যদি পাস ফাংশন প্রদত্ত ভেরিয়েবলটি পরিবর্তন করে এবং 0 ফাংশনটি না করে। তাহলে এই প্রোগ্রামটি প্রিন্ট করা উচিত?

int variable = 0;

void f() {
    if (modifies_variable(f, variable)) {
        /* do nothing */
    } else {
        /* modify variable */
        variable = 1;
    }
}

int main(int argc, char **argv) {
    if (modifies_variable(f, variable)) {
        printf("Modifies variable\n");
    } else {
        printf("Does not modify variable\n");
    }

    return 0;
}

12
নিস! আমি একজন মিথ্যাবাদী প্যারাডক্স am হিসাবে একটি প্রোগ্রামারের লেখা।
ক্রুমেলুর

28
থামানো সমস্যার অনস্বীকার্যতার জন্য এটি আসলে বিখ্যাত প্রমাণের একটি দুর্দান্ত অভিযোজন ।
কনস্ট্যান্টিন ওয়েটিজ

10
এই কংক্রিটের ক্ষেত্রে "modifies_variable" সত্যটি ফিরে আসা উচিত: কমপক্ষে একটি কার্যকর করার পথ রয়েছে যার মধ্যে ভেরিয়েবলটি সত্যিই সংশোধিত হয়। এবং সেই কার্যকরকরণের পথটি একটি বহিরাগত, অ-নিরস্তামূলক ক্রিয়াকলাপের জন্য কল করার পরে পৌঁছে যায় - সুতরাং পুরো ফাংশনটি হ'ল নির্দোষ। এই 2 কারণে, সংকলকটি হতাশাব্যঞ্জক দৃষ্টিভঙ্গি গ্রহণ করবে এবং সিদ্ধান্ত নেবে যে এটি ভেরিয়েবলটি সংশোধন করে। যদি কোনও পরিবর্তনশীল সংশোধন করার পথটি যদি একটি নির্ধারিত তুলনা (সংকলক দ্বারা যাচাইযোগ্য) পরে ফলস্বরূপ পৌঁছে যায় (যেমন "1 == 1") তবে সংকলক নিরাপদে বলতে পারে যে এই জাতীয় ফাংশন কখনই পরিবর্তনশীল পরিবর্তন করে না
জো পাইনেদা

6
@ জোপাইনাডা: প্রশ্নটি fপরিবর্তনশীলকে সংশোধন করে কিনা - তা পরিবর্তনশীলকে পরিবর্তন করতে পারে কিনা তা নয়। এই উত্তরটি সঠিক।
নিল জি

4
@ জোপেইনাডা: modifies_variableসংকলক উত্স থেকে কোডটি অনুলিপি / আটকানো থেকে কোনও কিছুই আমাকে বাধা দেয় না , আপনার যুক্তি পুরোপুরি বাতিল করে দেয়। (ওপেন-সোর্স ধরে
নিচ্ছেন

60

বিভ্রান্ত করবেন না "এই ইনপুটগুলি প্রদত্ত একটি পরিবর্তনশীলকে উইল করবে বা সংশোধন করবে না" "এর জন্য " একটি কার্যকরকরণের পথ রয়েছে যা ভেরিয়েবলকে সংশোধন করে। "

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

তবে পরবর্তী বিবৃতিটি পার্স ট্রিকে দেখে নির্ধারণ করা যেতে পারে, যা সমস্ত অপ্টিমাইজ করা সংকলকরা করেন। তাদের কারণটি হ'ল খাঁটি ফাংশন (এবং উল্লেখযোগ্যভাবে স্বচ্ছ ফাংশনগুলি, কিছুটা স্বচ্ছ সংজ্ঞায়নের জন্য ) প্রয়োগ করা যায় এমন সমস্ত ধরণের চমৎকার অপ্টিমাইজেশন রয়েছে যেমন সহজেই অনন্য হয়ে যাওয়া বা সংকলন-সময়ে তাদের মান নির্ধারণ করা; তবে কোনও ফাংশন খাঁটি কিনা তা জানতে, আমাদের এটি জানতে হবে যে এটি কখনও কোনও পরিবর্তনশীল পরিবর্তন করতে পারে কিনা ।

সুতরাং, সি ++ সম্পর্কে যা অবাক করা বক্তব্য বলে মনে হচ্ছে তা আসলে সমস্ত ভাষা সম্পর্কে একটি তুচ্ছ বিবৃতি।


5
এটি হ'ল সেরা উত্তর ইমো, এই পার্থক্যটি করা গুরুত্বপূর্ণ।
আঙ্কেলজিভ

"তুচ্ছভাবে অসম্ভব"?
কিপ করুন

2
@ কিপ "সিদ্ধান্ত নেওয়ার ক্ষেত্রে তুচ্ছভাবে অসম্ভব" এর অর্থ সম্ভবত "সিদ্ধান্ত নেওয়া অসম্ভব এবং প্রমাণটি তুচ্ছ"।
ফ্রেডওভারফ্লো

28

আমি মনে করি "C ++ ফাংশনটি একটি নির্দিষ্ট ভেরিয়েবলের মান" উইল "পরিবর্তন করবে কিনা তার মূল শব্দটি। একটি সংকলক তৈরি করা অবশ্যই সম্ভব যা কোনও সি ++ ফাংশনকে নির্দিষ্ট ভেরিয়েবলের মান পরিবর্তন করার অনুমতি দেয় কিনা তা যাচাই করে , আপনি যে পরিবর্তনটি ঘটতে চলেছেন তা আপনি দৃty়তার সাথে বলতে পারবেন না:

void maybe(int& val) {
    cout << "Should I change value? [Y/N] >";
    string reply;
    cin >> reply;
    if (reply == "Y") {
        val = 42;
    }
}

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

12
@ মার্টিনএপজ দ্বারা "আমার মানে" পরিবর্তিত হতে দেওয়া হচ্ছে "," সম্ভবত পরিবর্তন করতে পারে না "এমনটি হতে পারে। আমি বিশ্বাস করি যে-ওপেন constচেক সম্পর্কে কথা বলার সময় ওপি-র মনে এইটাই ছিল।
ডেসব্লিংকনলাইট

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

@ মার্টিনএপজ: "এবং এমন কোনও গণনীয় ফাংশন নেই যা কোনও গণনাযোগ্য ফাংশনের সমস্ত সম্ভাব্য রিটার্ন মান বলতে পারে"। আমি মনে করি "সমস্ত সম্ভাব্য রিটার্ন মান" পরীক্ষা করা একটি ভুল পদ্ধতির। এখানে গাণিতিক সিস্টেম রয়েছে (ম্যাক্সিমা, ম্যাথল্যাব) যা সমীকরণগুলিকে সমাধান করতে পারে, যার অর্থ এটি ফাংশনগুলিতে অনুরূপ পদ্ধতির প্রয়োগ করা বোধগম্য হবে। অর্থাৎ এটি বেশ কয়েকটি অজানা সাথে সমীকরণ হিসাবে বিবেচনা করে। সমস্যাগুলি হ'ল প্রবাহ নিয়ন্ত্রণ + পার্শ্ব প্রতিক্রিয়া => অবিশ্বাস্য পরিস্থিতি। আইএমও, সেগুলি ছাড়াই (কার্যকরী ভাষা, কোনও অ্যাসাইনমেন্ট / পার্শ্ব প্রতিক্রিয়া) না থাকলে কোনও পাথ প্রোগ্রামটি গ্রহণ করবে তা অনুমান করা সম্ভব ছিল
সিগটর্ম

16

আমি মনে করি না যে থামিয়ে দেওয়া সমস্যাটি বোঝাতে প্রয়োজনীয় হবে যে আপনি কোনও সংকলনের সময় অ্যালগোরিদমিকভাবে জানতে পারবেন না যে প্রদত্ত ফাংশনটি একটি নির্দিষ্ট ভেরিয়েবল পরিবর্তন করবে কিনা।

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

int y;

int main(int argc, char *argv[]) {
   if (argc > 2) y++;
}

সংকলক yসংশোধন হবে কিনা তা নিশ্চিত করে ভবিষ্যদ্বাণী করতে পারে?


7

এটি করা যেতে পারে এবং সংযোজকরা কিছু ফাংশনগুলির জন্য এটি সর্বদা করছেন, এটি উদাহরণস্বরূপ সাধারণ ইনলাইন অ্যাক্সেসর বা অনেক খাঁটি ফাংশনগুলির জন্য একটি তুচ্ছ অনুকূলকরণ।

যা অসম্ভব তা সাধারণ ক্ষেত্রে এটি জানা।

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

তবে আপনার কনস্ট ব্যবহার করা উচিত, গ্লোবালগুলি এড়ানো উচিত, পয়েন্টারগুলিতে রেফারেন্সগুলি পছন্দ করা উচিত, সম্পর্কযুক্ত কাজের জন্য পরিবর্তনশীলগুলির পুনরায় ব্যবহার করা এড়ানো উচিত aggressive


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

ওভারলোডিং একটি সংকলন-সময় ধারণা। আপনি সম্ভবত "ওভাররাইড পদ্ধতি" বোঝাতে চেয়েছিলেন।
ফ্রেডওভারফ্লো 26'14

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

6

এটি ব্যাখ্যা করার জন্য একাধিক উপায় রয়েছে যার মধ্যে একটি হলটিং সমস্যা :

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

অ্যালান টুরিং 1936 সালে প্রমাণ করেছিলেন যে সমস্ত সম্ভাব্য প্রোগ্রাম-ইনপুট জোড়গুলির জন্য থামানো সমস্যা সমাধানের জন্য একটি সাধারণ অ্যালগরিদম উপস্থিত থাকতে পারে না।

যদি আমি এমন কোনও প্রোগ্রাম লিখি যা দেখে মনে হয়:

do tons of complex stuff
if (condition on result of complex stuff)
{
    change value of x
}
else
{
    do not change value of x
}

xপরিবর্তনের মান কি ? এটি নির্ধারণ করতে, আপনাকে প্রথমে নির্ধারণ করতে হবে যে do tons of complex stuffঅংশটি শর্তটি আগুনের কারণ করে - বা আরও বেসিক, এটি বন্ধ রয়েছে কিনা। এটি এমন কিছু যা সংকলক করতে পারে না।


6

সত্যিই অবাক হয়ে যায় যে থামার সমস্যাটি সরাসরি ব্যবহার করে এমন কোনও উত্তর নেই! এই সমস্যাটি থেকে থামার সমস্যার থেকে খুব সরল হ্রাস রয়েছে।

কল্পনা করুন যে সংকলকটি কোনও ফাংশন একটি ভেরিয়েবলের মান পরিবর্তন করেছে কিনা তা বলতে পারে। তারপরে এটি অবশ্যই নীচের ফাংশনটি y এর মান পরিবর্তন করে কিনা তা ধরে নিতে সক্ষম হবেন, ধরে নিয়েই এক্সের মানটি প্রোগ্রামের বাকি অংশে সমস্ত কলগুলিতে ট্র্যাক করা যায়:

foo(int x){
   if(x)
       y=1;
}

এখন, আমাদের যে কোনও প্রোগ্রামের জন্য, আসুন এটি আবার লিখুন:

int y;
main(){
    int x;
    ...
    run the program normally
    ...
    foo(x);
}

লক্ষ্য করুন যে, যদি এবং কেবলমাত্র, যদি আমাদের প্রোগ্রামটি y এর মান পরিবর্তন করে তবে এটি কি সমাপ্ত হবে - ফু () শেষ হওয়ার আগে এটি শেষ কাজ করে thing এর অর্থ আমরা থামার সমস্যাটি সমাধান করেছি!

উপরের হ্রাস আমাদের যা দেখায় তা হ'ল কোনও ভেরিয়েবলের মান পরিবর্তন হয় কিনা তা নির্ধারণের সমস্যাটি থামানো সমস্যার মতো কমপক্ষে কঠোর। থামানো সমস্যাটি অসম্পূর্ণ হিসাবে পরিচিত, তাই এটি অবশ্যই হওয়া উচিত।


আমি নিশ্চিত নই যে আমি আপনার যুক্তি অনুসরণ করছি, কেন আমাদের প্রোগ্রামটি যদি এর মান পরিবর্তন করে তবে এটি বন্ধ হয় y। আমার কাছে foo()দ্রুত ফেরতের মতো দেখায় এবং তারপরে main()প্রস্থান করে। (এছাড়াও, আপনি foo()কোনও যুক্তি ছাড়াই কল করছেন ... এটি আমার বিভ্রান্তির অংশ))
লার্শ

1
@ লার্শ: যদি পরিবর্তিত প্রোগ্রামটি সমাপ্ত হয়, তবে এটির শেষ কর্মটি এফ হয়েছিল। যদি y সংশোধন করা হয়, f কে বলা হয়েছিল (অন্যান্য বিবৃতিগুলি y পরিবর্তন করতে পারে না, যেহেতু এটি শুধুমাত্র সংশোধন দ্বারা প্রবর্তিত হয়েছিল)। সুতরাং, যদি y সংশোধন করা হয়, প্রোগ্রামটি সমাপ্ত হয়।
MSalters

4

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

 void foo(int& x)
 {
    ifstream f("f.dat", ifstream::binary);
    f.read((char *)&x, sizeof(x));
 }

এবং এটি আমাদের "বার.cpp" এ রয়েছে:

void bar(int& x)
{
  foo(x);
}

সংকলকটি কীভাবে "জানতে পারে" যা xপরিবর্তিত হয় না (বা আরও সঠিকভাবে পরিবর্তিত হচ্ছে) bar?

আমি নিশ্চিত যে আমরা আরও জটিল কিছু নিয়ে আসতে পারি, যদি এটি যথেষ্ট জটিল না হয়।


সংকলকটি জানতে পারে যে x বারে পরিবর্তন হচ্ছে না যদি বার এক্স পাস-বাই-রেফারেন্স-টু-কনস্টের হিসাবে পাস করা হয়, তাই না?
ক্রিকেটার

হ্যাঁ, তবে আমি যদি const_castfoo এ যুক্ত করি তবে এটি xপরিবর্তন করতে পারে - আমি সেই চুক্তি লঙ্ঘন করবো যা বলে যে আপনি constভেরিয়েবল পরিবর্তন করবেন না , তবে যেহেতু আপনি কোনও কিছুকে "আরও কনস্ট" রূপান্তর করতে পারেন, এবং const_castবিদ্যমান, ভাষার ডিজাইনারদের অবশ্যই এই ধারণা ছিল যে constমূল্যবোধের পরিবর্তনের প্রয়োজন হতে পারে এমন বিশ্বাস করার জন্য বেশিরভাগ কারণ রয়েছে ।
ম্যাটস পিটারসন

@ ম্যাটস পিটারসন: আমি বিশ্বাস করি যে আপনি যদি কনস্টকাস্ট করেন তবে আপনি যে সমস্ত টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো করে ফেলতে পারেন।
জ্যান লিংস

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

1

সংকলকটির পক্ষে নির্ধারণ করা যেমন ভেরিয়েবল পরিবর্তন করা হবে কিনা তা সাধারণভাবে অসম্ভব ।

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


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

এটি অবশ্যই কার্যকর হবে। এটির জন্য অবশ্যই নিদর্শন রয়েছে তবে সি ++ (এবং অন্যান্য অনেক ভাষা) এ "প্রতারণা" করা সর্বদা সম্ভব।
ক্রুমেলুর

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

1

প্রশ্নটি আরও সুনির্দিষ্ট করার জন্য আমি পরামর্শ দিচ্ছি যে বইয়ের লেখক মনে রেখেছিলেন, নিম্নলিখিত সীমাবদ্ধতার সেটগুলি হতে পারে:

  1. ধরুন যে সংকলকটি একটি ভেরিয়েবলের কনস্ট-নেসের সাথে সম্পর্কিত একটি নির্দিষ্ট ফাংশনের আচরণ পরীক্ষা করে দেখছে। নির্ভুলতার জন্য একটি সংকলককে ধরে নিতে হবে (নীচে বর্ণিত হিসাবে এলিয়াসিংয়ের কারণে) যদি ফাংশনটি অন্য ফাংশন বলে ভেরিয়েবল পরিবর্তন করা হয়, সুতরাং অনুমান # 1 কেবলমাত্র কোড টুকরাগুলিতে প্রযোজ্য যা ফাংশন কল করে না।
  2. ধরে নিন ভেরিয়েবলটি একটি অ্যাসিনক্রোনাস বা সমবর্তী ক্রিয়াকলাপ দ্বারা সংশোধিত হয়নি।
  3. ধরুন যে সংকলকটি কেবল পরিবর্তনশীলটি সংশোধন করা যাবে কিনা তা নির্ধারণ করছে, এটি পরিবর্তিত হবে কিনা। অন্য কথায় সংকলকটি কেবল স্থির বিশ্লেষণ করছে।
  4. ধারনা করুন যে সংকলকটি সঠিকভাবে কার্যকরী কোড বিবেচনা করছে (অ্যারে ওভাররান / আন্ডারআনস, খারাপ পয়েন্টার ইত্যাদি বিবেচনা করবেন না)

সংকলক নকশার প্রসঙ্গে, আমি ধারণা করি যে কোড জেনের নির্ভুলতা এবং / অথবা কোড অপ্টিমাইজেশনের প্রসঙ্গে সংকলক লেখকের দৃষ্টিতে 1,3,4 অনুমানগুলি নির্ভুল ধারণা তৈরি করে। অ্যাসোশন 2 টি অস্থির কীওয়ার্ডের অনুপস্থিতিতে অর্থবোধ করে। এবং এই অনুমানগুলিও প্রস্তাবিত উত্তরের বিচারকে আরও বেশি সংজ্ঞাবদ্ধ করার জন্য যথেষ্ট প্রশ্নটিকে কেন্দ্র করে :-)

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

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


0

এমনকি যদি কোনও ভেরিয়েবল ঘোষিত হয় const, তার অর্থ এই নয় যে কোনও খারাপভাবে লিখিত কোড এটি ওভাররাইট করতে পারে।

//   g++ -o foo foo.cc

#include <iostream>
void const_func(const int&a, int* b)
{
   b[0] = 2;
   b[1] = 2;
}

int main() {
   int a = 1;
   int b = 3;

   std::cout << a << std::endl;
   const_func(a,&b);
   std::cout << a << std::endl;
}

আউটপুট:

1
2

এটি হ'ল কারণ aএবং bস্ট্যাক ভেরিয়েবলগুলি এবং b[1]ঠিক একই মেমরির অবস্থান হিসাবে ঘটে a
লাকাটা

1
-1। সংজ্ঞায়িত আচরণ কম্পাইলারের আচরণের সমস্ত বিধিনিষেধ অপসারণ করে।
MSalters

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

0

আমার মন্তব্যগুলিকে আরও প্রসারিত করার জন্য, বইটির পাঠ্যটি অস্পষ্ট যা কোন বিষয়টি বিবেচনা করে না।

যেমনটি আমি মন্তব্য করেছি, সেই বইটি বলতে চেষ্টা করছে, "আসুন প্রতিটি লেখা অনুমানযোগ্য সি ++ ক্রিয়াকলাপ লিখতে অসীম বানর পেতে পারি cases এমন কিছু ঘটনা ঘটবে যেখানে আমরা যদি একটি পরিবর্তনশীল বাছাই করি যে (বানররা কিছু নির্দিষ্ট ক্রিয়া লিখেছিল) ব্যবহার করে, ফাংশনটি সেই পরিবর্তনশীলটি পরিবর্তন করবে কিনা তা আমরা কাজ করতে পারি না। "

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

এই ফাংশনটি এত সহজে বিশ্লেষণ করা যায়:

static int global;

void foo()
{
}

"foo" পরিষ্কারভাবে "গ্লোবাল" পরিবর্তন করে না। এটি কিছুতেই কোনও সংশোধন করে না এবং একটি সংকলক এটি খুব সহজেই কাজ করতে পারে।

এই ফাংশনটি এত বিশ্লেষণ করা যায় না:

static int global;

int foo()
{
    if ((rand() % 100) > 50)
    {
        global = 1;
    }
    return 1;

যেহেতু "foo" এর ক্রিয়াগুলি এমন কোনও মানের উপর নির্ভর করে যা রানটাইমের সময় পরিবর্তিত হতে পারে, তাই এটি সংকলনের সময় স্পষ্টতই নির্ধারণ করা যায় না "গ্লোবাল" সংশোধন করবে কিনা তা ।

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


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

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