কল স্ট্যাকের স্থির সর্বোচ্চ আকার কেন থাকবে?


46

কয়েকটি প্রোগ্রামিং ল্যাঙ্গুয়েজ নিয়ে কাজ করার পরে, আমি সর্বদা ভাবছিলাম যে থ্রেড স্ট্যাকের পূর্বনির্ধারিত সর্বোচ্চ আকার রয়েছে, প্রয়োজন অনুযায়ী স্বয়ংক্রিয়ভাবে প্রসারণের পরিবর্তে। 

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

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

কেন এমন ঘটনা ঘটে যে বেশিরভাগ (সমস্ত না থাকলে) রানটাইম পরিবেশগুলি রানটাইমের সময় স্ট্যাক বাড়তে পারে তার আকারের সর্বাধিক সীমা নির্ধারণ করে?


13
এই ধরণের স্ট্যাক হল অবিচ্ছিন্ন ঠিকানার স্থান যা নিঃশব্দে পর্দার পিছনে সরানো যায় না। 32 বিট সিস্টেমে ঠিকানা স্থান মূল্যবান।
কোডসইনচাউস

7
আইভরি-টাওয়ার আইডিয়াসগুলির উপস্থিতি হ্রাস করার জন্য যেমন পুনরাবৃত্তি একাডেমিয়া থেকে বেরিয়ে আসা এবং বাস্তব জগতে সমস্যা হ্রাস করার মতো কোডের পাঠযোগ্যতা এবং মালিকানার মোট ব্যয় বাড়ানো;)
ব্র্যাড থমাস

6
@ ব্র্যাড থমাস টেল কল অপটিমাইজেশনের জন্য এটি।
জ্যাব

3
@ জোহানউউ: এটি এখন যা ঘটায় তা ঠিক খানিক পরে: স্মৃতিশক্তি শেষ হয়ে যায়।
জার্গ ডব্লু মিট্টাগ

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

উত্তর:


13

এমন কোনও অপারেটিং সিস্টেম লিখতে সম্ভব যা ঠিকানা জায়গাতে স্ট্যাকের সংযোগের প্রয়োজন হয় না। মূলত কলিং কনভেনশনে আপনার কিছু অতিরিক্ত গন্ডগোলের দরকার রয়েছে তা নিশ্চিত করার জন্য:

  1. আপনি যে ফাংশনটি কল করছেন তার জন্য যদি বর্তমান স্ট্যাকের পরিমাণে পর্যাপ্ত জায়গা না থাকে তবে আপনি একটি নতুন স্ট্যাকের পরিমাণ তৈরি করেন এবং কলটি করার অংশ হিসাবে স্ট্যাক পয়েন্টারটিকে এটির শুরুতে নির্দেশ করে যান।

  2. আপনি যখন সেই কলটি থেকে ফিরে আসেন তখন আপনি মূল স্ট্যাকের পরিমাণে ফিরে স্থানান্তর করেন। সম্ভবত আপনি একই থ্রেড দ্বারা ভবিষ্যতের ব্যবহারের জন্য (1) এ তৈরি করাটিকে ধরে রাখবেন। নীতিগতভাবে আপনি এটি মুক্তি দিতে পারেন, তবে সেই পথে বরং অদক্ষ মামলা রয়েছে যেখানে আপনি একটি লুপে সীমানা পেরিয়ে পিছনে হাঁপিয়ে যাচ্ছেন এবং প্রতিটি কলটির জন্য মেমরি বরাদ্দ থাকা দরকার।

  3. setjmpএবং longjmp, বা আপনার ওএস-এর নিয়ন্ত্রণের অ-লোকাল ট্রান্সফারের জন্য যা কিছু সমতুল্য রয়েছে তা কার্যকর রয়েছে এবং যখন প্রয়োজন হবে তখন সঠিকভাবে পুরানো স্ট্যাকের পরিমাণে ফিরে যেতে পারে।

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

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

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


36

এই ডেটা স্ট্রাকচারগুলির সাধারণত ওএস স্ট্যাকের বৈশিষ্ট্য নেই:

  • লিঙ্কযুক্ত তালিকাগুলির জন্য ঠিকানার জায়গার প্রয়োজন হয় না। সুতরাং তারা যখন বাড়াবে তারা যেখানেই চাইবে সেখান থেকে একটি মেমরি যোগ করতে পারে।

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

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

64৪-বিট সিস্টেমে আপনি তুলনামূলকভাবে কম দামের সাথে তুলনামূলকভাবে বড় স্ট্যাকগুলি কনফিগার করতে পারেন, কারণ ঠিকানার জায়গাগুলি যথেষ্ট এবং শারীরিক স্মৃতি কেবলমাত্র যখন আপনি এটি ব্যবহার করেন তখন বরাদ্দ হয়ে যায়।


1
এটি একটি ভাল উত্তর এবং আমি আপনার অর্থ অনুসরণ করি তবে "ধারাবাহিক" এর বিপরীতে "সংঘবদ্ধ" মেমরি ব্লক শব্দটি কি নয়, যেহেতু প্রতিটি স্মৃতি ইউনিটের নিজস্ব অনন্য ঠিকানা রয়েছে?
ড্যান্ক

2
"একটি কল স্ট্যাকের সীমাবদ্ধতা থাকতে হবে না" এর জন্য +1 এটি প্রায়শই সরলতা এবং সম্পাদনের জন্য সেভাবে বাস্তবায়িত হয়, তবে এটি হওয়ার দরকার নেই।
পল ড্রাগার

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

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

26

বাস্তবে, স্ট্যাকটি বৃদ্ধি করা কঠিন (এবং কখনও কখনও অসম্ভব)। ভার্চুয়াল মেমরির কেন কিছু বোঝার প্রয়োজন তা বোঝার জন্য।

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

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

তাহলে কেন কোনও প্রোগ্রামের পুরো ঠিকানা জায়গায় অ্যাক্সেস দেওয়া বাঞ্ছনীয় নয়? কারণ সেই স্মৃতিটি অদলবদলের বিরুদ্ধে "কমিট চার্জ" গঠন করে; যে কোনও সময় কোনও প্রোগ্রামের জন্য যে কোনও বা সমস্ত মেমরির অন্য কোনও প্রোগ্রামের স্মৃতির জন্য জায়গা তৈরি করতে অদলবদল করতে হবে। যদি প্রতিটি প্রোগ্রাম সম্ভাব্যভাবে 2 জিবি অদলবদ গ্রহণ করতে পারে তবে তা হয় আপনার সমস্ত প্রোগ্রামের জন্য পর্যাপ্ত পরিমাণে অদলবদল সরবরাহ করতে হবে বা দুটি প্রোগ্রামকে যতটা সম্ভব তার চেয়ে বেশি প্রয়োজন হবে এমন সুযোগটি নিতে হবে।

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

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

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


3
বর্তমান x86-64 সিপিইউগুলিতে কেবল ঠিকানার জায়গার 48 বিট রয়েছে
কোডসইনচোস

আমি যতদূর জানি, Linux করে স্ট্যাক পরিবর্তনশীল বেড়ে ওঠে একটি প্রক্রিয়া চেষ্টা বর্তমানে বরাদ্দ স্ট্যাক নীচের অঞ্চলটি অধিকার অ্যাক্সেস করতে হলে, বিঘ্ন শুধু স্ট্যাকের মেমরি একটি অতিরিক্ত পৃষ্ঠা ম্যাপিং পরিবর্তে প্রক্রিয়া segfaulting দ্বারা পরিচালিত হয়।
সিমেস্টার

2
@ মাস্টার: সত্য, তবে কেডিগ্রিগরি বলতে "স্ট্যাক বাড়ানো" বলতে বোঝায় না। স্ট্যাক হিসাবে ব্যবহারের জন্য বর্তমানে মনোনীত একটি ঠিকানা সীমা রয়েছে। আপনি প্রয়োজন অনুসারে ধীরে ধীরে আরও বেশি শারীরিক মেমরি ম্যাপ করার কথা বলছেন। কেডগ্রিগরি বলছে যে ব্যাপ্তি বাড়ানো কঠিন বা অসম্ভব।
স্টিভ জেসোপ

x86 একমাত্র আর্কিটেকচার নয়, এবং 48 বিট এখনও কার্যকরভাবে অসীম
কেডগ্রিগরি

1
বিটিডাব্লু, আমি মনে করি আমার দিনগুলি x86 এর সাথে কাজ করা এত মজা নয়, মূলত সেগমেন্টেশনকে মোকাবেলা করার কারণে। আমি এমসি 68 কে প্ল্যাটফর্মগুলিতে অনেক বেশি পছন্দ করেছি প্রকল্পগুলি ;-)
কেডগ্রিগরি

4

সর্বাধিক আকারের স্ট্যাকটি সর্বব্যাপী নয়।

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

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

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

  • অস্থাবর স্ট্যাকস: যখন অন্য কিছু থাকার কারণে যখন সামঞ্জস্যপূর্ণ স্ট্যাকটি আর বাড়তে পারে না, তখন আরও খালি স্থান সহ এটিকে মেমরির অন্য কোনও জায়গায় নিয়ে যান
  • বিচ্ছিন্ন স্ট্যাকগুলি: সম্পূর্ণ স্ট্যাকটি একটি একক সঙ্গতিপূর্ণ মেমরি স্পেসে বরাদ্দ না করে একাধিক মেমরি স্পেসে বরাদ্দ করুন
  • হ্যাপ-বরাদ্দ স্ট্যাকগুলি: স্ট্যাক এবং হিপগুলির জন্য পৃথক মেমরি অঞ্চল থাকার পরিবর্তে, কেবল স্তূপে স্ট্যাক বরাদ্দ করুন; যেমন আপনি নিজেরাই লক্ষ্য করেছেন, গাদা-বরাদ্দ হওয়া ডেটা স্ট্রাকচারগুলিকে প্রয়োজনমতো বৃদ্ধি এবং সঙ্কুচিত হওয়ার কোনও সমস্যা নেই
  • স্ট্যাকগুলি একেবারেই ব্যবহার করবেন না: এটিও একটি বিকল্প, উদাহরণস্বরূপ স্ট্যাকের মধ্যে ফাংশন অবস্থার ট্র্যাক রাখার পরিবর্তে ফাংশনটি কলির সাথে একটি ধারাবাহিকতা পাস করতে হবে

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


1

স্ট্যাকের জন্য অনুরোধ করা হলে ওএসকে একটি জটিল ব্লক দিতে হয়। এটিই করতে পারে একমাত্র উপায় যদি সর্বাধিক আকার নির্দিষ্ট করা থাকে।

উদাহরণস্বরূপ, আসুন আমরা মেমরিটি অনুরোধের সময় এইরকম দেখাচ্ছে (এক্সগুলি ব্যবহার করা হয়, ওএস অব্যবহৃত):

XOOOXOOXOOOOOX

যদি 6 টি স্ট্যাক আকারের জন্য একটি অনুরোধ থাকে তবে 6 টিরও বেশি উপলব্ধ থাকলেও ওএস উত্তরটি উত্তর দেবে না। যদি আকার 3 স্ট্যাকের জন্য অনুরোধ করা হয়, তবে ওএস উত্তরটি পর পর 3 টি খালি স্লট (ওস) এর একটির ক্ষেত্র হবে।

এছাড়াও, পরবর্তী সামঞ্জস্যপূর্ণ স্লটটি দখল করা হলে কেউ বৃদ্ধির অনুমতি দিতে অসুবিধা দেখতে পাবে।

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

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


1

লিনাক্সে, এটি নিখুঁতভাবে একটি সংস্থান সীমা যা তারা ক্ষতিকারক পরিমাণে সংস্থান গ্রহণ করার আগে পলাতক প্রক্রিয়াগুলি ধ্বংস করতে উপস্থিত হয়। আমার ডিবিয়ান সিস্টেমে, নিম্নলিখিত কোড

#include <sys/resource.h>
#include <stdio.h>

int main() {
    struct rlimit limits;
    getrlimit(RLIMIT_STACK, &limits);
    printf("   soft limit = 0x%016lx\n", limits.rlim_cur);
    printf("   hard limit = 0x%016lx\n", limits.rlim_max);
    printf("RLIM_INFINITY = 0x%016lx\n", RLIM_INFINITY);
}

আউটপুট উত্পাদন করে

   soft limit = 0x0000000000800000
   hard limit = 0xffffffffffffffff
RLIM_INFINITY = 0xffffffffffffffff

দ্রষ্টব্য, যে হার্ড সীমাটি সেট করা আছে RLIM_INFINITY: প্রক্রিয়াটিকে তার নরম সীমাটি যে কোনও পরিমাণে বাড়ানোর অনুমতি দেওয়া হয় । যাইহোক, যতক্ষণ না প্রোগ্রামারকে বিশ্বাস করার কোনও কারণ নেই যে প্রোগ্রামটি সত্যই অস্বাভাবিক পরিমাণে স্ট্যাক মেমরির প্রয়োজন, প্রক্রিয়াটি মারা যাবে যখন এটি আটটি মেগাবাইটের স্ট্যাক আকার ছাড়িয়ে যাবে।

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


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


2
এটি কেবল প্রথম থ্রেডের স্ট্যাক। নতুন থ্রেডগুলিকে নতুন স্ট্যাক বরাদ্দ করতে হবে এবং এটি সীমিত কারণ তারা অন্যান্য বস্তুর মধ্যে চলে যাবে।
জ্যান লিংস

0

সর্বাধিক কারণ যে স্ট্যাকের আকার স্ট্যাটিক হয় সংজ্ঞা "সর্বাধিক" । যে কোনও কিছুর উপরে সর্বাধিক যে কোনও ধরণের সীমাবদ্ধ চিত্র agreed যদি এটি স্বতঃস্ফূর্তভাবে চলমান লক্ষ্য হিসাবে আচরণ করে তবে এটি সর্বাধিক নয়।

ভার্চুয়াল-মেমরি অপারেটিং সিস্টেমের স্ট্যাকগুলি প্রকৃতপক্ষে সর্বাধিক অবধি গতিশীল হয়

যার কথা বললে এটি স্থির হতে হবে না। বরং এটি প্রতি-প্রক্রিয়া বা প্রতি-থ্রেড ভিত্তিতে এমনকি কনফিগারযোগ্য হতে পারে।

যদি প্রশ্ন করা হয় "কেন হয় (একটি কৃত্রিম আরোপিত এক সাধারণত অনেক উপলব্ধ মেমরি কম,) সেখানে সর্বোচ্চ স্ট্যাকের আকার"?

একটি কারণ হ'ল বেশিরভাগ অ্যালগরিদমের জন্য প্রচুর পরিমাণে স্ট্যাক স্পেসের প্রয়োজন হয় না। একটি বড় স্ট্যাক একটি সম্ভাব্য পলাতক পুনরাবৃত্তির ইঙ্গিত । এটি সমস্ত উপলব্ধ মেমরির বরাদ্দের আগে পালানো পুনরাবৃত্তি বন্ধ করা ভাল to পলাতকী পুনরাবৃত্তি মনে হচ্ছে এমন একটি সমস্যা হ'ল ডিজেনরেট স্ট্যাক ব্যবহার, সম্ভবত একটি অপ্রত্যাশিত পরীক্ষার কেস দ্বারা ট্রিগার করা। উদাহরণস্বরূপ, ধরুন, বাইনারিটির জন্য কোনও পার্সার, ইনফিক্স অপারেটর ডান অপরেন্ডে পুনরাবৃত্তি করে কাজ করে: প্রথম অপারেন্ডকে পার্স করুন, স্ক্যান অপারেটর, বাকী বাক্সটিকে পার্স করুন। এর অর্থ এই যে স্ট্যাকের গভীরতা প্রকাশের দৈর্ঘ্য সমানুপাতিক: a op b op c op d ...। এই ফর্মটির একটি বিশাল পরীক্ষার ক্ষেত্রে একটি বিশাল স্ট্যাকের প্রয়োজন হবে। যুক্তিযুক্ত স্ট্যাকের সীমাটি হিট হওয়ার পরে প্রোগ্রামটি বাতিল করা এটিকে ধরবে।

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

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


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