গতিশীলভাবে সংযুক্ত থাকলে কোনও ভাগ করা লাইব্রেরিতে গ্লোবাল এবং স্ট্যাটিক ভেরিয়েবলগুলির কী ঘটে?


127

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

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

  • এই অ্যাপ্লিকেশনটি যখন লোড-টাইম গতিশীল লিঙ্ক সহ একটি মডিউল A ব্যবহার করে তখন কী ঘটে? আমি ধরে নিই যে ডিএলএল এর গ্লোবাল এবং স্ট্যাটিক্সের জন্য একটি বিভাগ আছে। অপারেটিং সিস্টেম এগুলি লোড করে? যদি তা হয় তবে তারা কোথায় বোঝাবেন?

  • এবং যখন অ্যাপ্লিকেশনটি রান-টাইম ডায়নামিক লিঙ্কিংয়ের সাথে একটি মডিউল বি ব্যবহার করে তখন কী ঘটে?

  • আমার আবেদনে যদি আমার দুটি মডিউল থাকে যা উভয় A এবং B ব্যবহার করে, তবে এ এবং বি এর গ্লোবালগুলির কপিগুলি নীচে উল্লিখিত হিসাবে তৈরি করা হয়েছে (যদি তারা পৃথক প্রক্রিয়া হয়)?

  • ডিএলএলস এ এবং বি অ্যাপ্লিকেশন গ্লোবালগুলিতে অ্যাক্সেস পেতে পারে?

(দয়া করে আপনার কারণগুলিও বর্ণনা করুন)

এমএসডিএন থেকে উদ্ধৃতি :

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

এবং থেকে এখানে :

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

ধন্যবাদ।


3
মডিউল দ্বারা আপনি সম্ভবত libs বোঝায় । মডিউলটি কী হবে তার আরও সুনির্দিষ্ট সংজ্ঞা এবং এখনকার নিয়মিত পাঠাগারগুলির চেয়ে আলাদা শব্দার্থবিজ্ঞানের সাথে সি ++ স্ট্যান্ডার্ডে মডিউল যুক্ত করার প্রস্তাব রয়েছে ।
ডেভিড রদ্রিগেজ - ড্রিবিস

আহ, এটা স্পষ্ট করা উচিত ছিল। আমি একটি সমাধানে বিভিন্ন প্রকল্পগুলি মডিউল হিসাবে বিবেচনা করি (ভিজ্যুয়াল স্টুডিওতে আমি অনেক বেশি কাজ করি)। এই মডিউলগুলি * .lib বা * .dll এর মধ্যে অন্তর্নির্মিত।
রাজা

3
@ ডেভিডরডগ্রিজেজ-ড্রিবিয়াস "মডিউল" শব্দটি হ'ল নির্বাহযোগ্য ফাইলগুলির জন্য একক (সম্পূর্ণ সংযুক্ত) সঠিক প্রযুক্তিগত শব্দ, যার মধ্যে রয়েছে: এক্সিকিউটেবল প্রোগ্রাম, ডায়নামিক-লিংক লাইব্রেরি (.dll) বা ভাগ করা অবজেক্টস (.so)। এটি এখানে পুরোপুরি উপযুক্ত এবং অর্থটি সঠিক এবং ভালভাবে বোঝা গেছে। "মডিউলগুলি" নামে কোনও মানক বৈশিষ্ট্য না পাওয়া পর্যন্ত এর সংজ্ঞাটি প্রচলিত remains
মিকারেল পারসন

উত্তর:


176

এটি উইন্ডোজ এবং ইউনিক্সের মতো সিস্টেমের মধ্যে একটি দুর্দান্ত পার্থক্য।

যেভাই হোকনা কেন:

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

সুতরাং, এখানে মূল সমস্যাটি সত্যই দৃশ্যমানতা

সমস্ত ক্ষেত্রে, staticগ্লোবাল ভেরিয়েবল (বা ফাংশন) কোনও মডিউল (dll / so বা নির্বাহযোগ্য) এর বাইরে থেকে কখনই দৃশ্যমান হয় না। সি ++ স্ট্যান্ডার্ডের এগুলির অভ্যন্তরীণ যোগসূত্র থাকা আবশ্যক, যার অর্থ তারা অনুবাদ ইউনিটের বাইরে দৃশ্যমান নয় (যা কোনও বস্তুর ফাইল হয়ে যায়) যেখানে তারা সংজ্ঞায়িত হয়। সুতরাং, যে সমস্যা নিষ্পত্তি।

এটি যখন জটিল হয় তখন আপনার externবৈশ্বিক চলকগুলি হ'ল । এখানে, উইন্ডোজ এবং ইউনিক্সের মতো সিস্টেমগুলি সম্পূর্ণ আলাদা।

উইন্ডোজ (.exe এবং .dll) এর ক্ষেত্রে, externগ্লোবাল ভেরিয়েবলগুলি রফতানি চিহ্নগুলির অংশ নয়। অন্য কথায়, বিভিন্ন মডিউলগুলি কোনওভাবেই অন্যান্য মডিউলগুলিতে সংজ্ঞায়িত গ্লোবাল ভেরিয়েবল সম্পর্কে সচেতন নয়। এর অর্থ হ'ল আপনি যদি লিঙ্কার ত্রুটিগুলি পেয়ে থাকেন তবে উদাহরণস্বরূপ, একটি এক্সিকিউটেবল তৈরি করতে যা externডিএলএল-এ সংজ্ঞায়িত ভেরিয়েবল ব্যবহার করার কথা বলে মনে করা হচ্ছে , কারণ এটি অনুমোদিত নয়। আপনাকে সেই বাহ্যিক ভেরিয়েবলের সংজ্ঞা সহ একটি অবজেক্ট ফাইল (বা স্ট্যাটিক লাইব্রেরি) সরবরাহ করতে হবে এবং এক্সিকিউটেবল এবং ডিএলএল উভয়ের সাথে এটি স্ট্যাটিকভাবে লিঙ্ক করতে হবে , যার ফলে দুটি স্বতন্ত্র গ্লোবাল ভেরিয়েবল (একটি এক্সিকিউটেবলের সাথে সম্পর্কিত এবং একটি ডিএলএল এর অন্তর্গত) )।

উইন্ডোজে আসলে গ্লোবাল ভেরিয়েবল এক্সপোর্ট করতে আপনাকে ফাংশন এক্সপোর্ট / ইম্পোর্ট সিনট্যাক্সের অনুরূপ একটি সিনট্যাক্স ব্যবহার করতে হবে, অর্থাত:

#ifdef COMPILING_THE_DLL
#define MY_DLL_EXPORT extern "C" __declspec(dllexport)
#else
#define MY_DLL_EXPORT extern "C" __declspec(dllimport)
#endif

MY_DLL_EXPORT int my_global;

আপনি যখন এটি করেন, বিশ্বব্যাপী পরিবর্তনশীল রফতানি চিহ্নগুলির তালিকায় যুক্ত হয় এবং অন্যান্য সমস্ত ফাংশনের মতো লিঙ্কযুক্ত হতে পারে can

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

অবশেষে, উভয় ক্ষেত্রেই উইন্ডোজ বা ইউনিক্সের মতো সিস্টেমের জন্য, আপনি গতিশীল লাইব্রেরির রান-টাইম লিঙ্কিং করতে পারেন , যেমন, LoadLibrary()/ GetProcAddress()/ FreeLibrary()অথবা dlopen()/ dlsym()/ ব্যবহার করে dlclose()। সেক্ষেত্রে আপনাকে ব্যবহার করতে ইচ্ছুক প্রতিটি প্রতীককে আপনাকে ম্যানুয়ালি পয়েন্টার পেতে হবে এবং এর মধ্যে আপনি ব্যবহার করতে চান এমন বৈশ্বিক পরিবর্তনগুলি অন্তর্ভুক্ত রয়েছে। গ্লোবাল ভেরিয়েবল জন্য, আপনি ব্যবহার করতে পারেন GetProcAddress()বা dlsym()ঠিক একই আপনার দেওয়া যে গ্লোবাল ভেরিয়েবল রপ্তানি প্রতীক তালিকা (পূর্ববর্তী অনুচ্ছেদের বিধি দ্বারা) এর অংশ হওয়ায়, কাজকর্মের জন্য কি হিসাবে।

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


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

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

4
কোন শ্রেণীর একটি ইনলাইন ফাংশনের অভ্যন্তরে স্থির পরিবর্তনগুলি কীভাবে সংজ্ঞায়িত করা যায়? উদাহরণস্বরূপ, শিরোলেখ ফাইলটিতে "শ্রেণি A {শূন্যপদ foo () {স্ট্যাটিক ইন্ট st_var = 0;}}" সংজ্ঞায়িত করুন এবং এটি মডিউল A এবং মডিউল বিতে অন্তর্ভুক্ত করবেন, A / B একই স্টার্ট_ভার ভাগ করবে বা প্রত্যেকটির নিজস্ব অনুলিপি থাকবে?
ক্যামিনো 21

2
@ ক্যামিনো যদি ক্লাসটি রফতানি করা হয় (যেমন এর সাথে সংজ্ঞায়িত __attribute__((visibility("default")))), তবে এ / বি একই স্টে_ভার ভাগ করবে। তবে ক্লাসটি যদি সংজ্ঞায়িত করা হয় __attribute__((visibility("hidden")))তবে মডিউল এ এবং মডিউল বি এর নিজস্ব অনুলিপি থাকবে, ভাগ হবে না।
ওয়েই গুও

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