উত্তর:
এটি কোনও উত্সের জন্য একটি বিমূর্ত রেফারেন্স মান, প্রায়শই স্মৃতি বা একটি উন্মুক্ত ফাইল বা পাইপ।
যথাযথভাবে , উইন্ডোজে, (এবং সাধারণত কম্পিউটারে) একটি হ্যান্ডেল এমন বিমূর্ততা যা এপিআই ব্যবহারকারীর কাছ থেকে একটি আসল মেমরি ঠিকানা লুকিয়ে রাখে, সিস্টেমটিকে প্রোগ্রামে স্বচ্ছভাবে মেমরির পুনর্গঠন করতে দেয়। একটি হ্যান্ডেলটিকে পয়েন্টারে সমাধান করা মেমরিটিকে লক করে এবং হ্যান্ডেলটি ছেড়ে দেওয়া পয়েন্টারটিকে অকার্যকর করে দেয়। এক্ষেত্রে এটি পয়েন্টারগুলির একটি সারণিতে সূচক হিসাবে ভাবেন ... আপনি সিস্টেম এপিআই কলগুলির জন্য সূচকটি ব্যবহার করেন এবং সিস্টেমটি ইচ্ছায় টেবিলের পয়েন্টারটি পরিবর্তন করতে পারে।
বিকল্প হিসাবে একটি আসল পয়েন্টার হ্যান্ডেল হিসাবে দেওয়া যেতে পারে যখন এপিআই লেখক ইচ্ছে করে যে এপিআই-র ব্যবহারকারীকে ঠিকানাটি কী নির্দেশ করে তাতে নির্দিষ্ট করে দেওয়া হয়; এক্ষেত্রে এটি অবশ্যই বিবেচনা করা উচিত যে হ্যান্ডেলটি যে কোনও সময় পরিবর্তিত হতে পারে (এপিআই সংস্করণ থেকে সংস্করণে বা এমনকি কলটি থেকে কলটি কল থেকে হ্যান্ডেলটি ফিরে আসে) - হ্যান্ডেলটিকে তাই কেবল অস্বচ্ছ মান হিসাবে বিবেচনা করা উচিত শুধুমাত্র এপিআই-এর অর্থবহ ।
আমার যোগ করা উচিত যে কোনও আধুনিক অপারেটিং সিস্টেমে, তথাকথিত "রিয়েল পয়েন্টার" এখনও প্রক্রিয়ার ভার্চুয়াল মেমরি স্পেসে অস্বচ্ছ হ্যান্ডেলগুলি থাকে, যা O / S প্রক্রিয়াটির মধ্যে পয়েন্টারগুলিকে অকার্যকর না করে মেমরি পরিচালনা এবং পুনঃব্যবস্থা করতে সক্ষম করে ables ।
এ HANDLE
একটি প্রসঙ্গ-নির্দিষ্ট অনন্য শনাক্তকারী। প্রসঙ্গ-নির্দিষ্ট করে বলতে গেলে, আমি বলতে চাইছি একটি প্রসঙ্গ থেকে প্রাপ্ত একটি হ্যান্ডেল অগত্যা অন্য কোনও অ্যাব্রিট্রি প্রসঙ্গে ব্যবহার করা যাবে না যা এটিতেও কাজ করে HANDLE
।
উদাহরণস্বরূপ, GetModuleHandle
বর্তমানে লোড হওয়া মডিউলে একটি অনন্য শনাক্তকারীকে ফেরত দেয়। ফিরে আসা হ্যান্ডেলটি অন্যান্য ফাংশনগুলিতে ব্যবহার করা যেতে পারে যা মডিউল হ্যান্ডেলগুলি গ্রহণ করে। এটি এমন ফাংশনগুলিতে দেওয়া যায় না যা অন্যান্য ধরণের হ্যান্ডলগুলি প্রয়োজন। উদাহরণস্বরূপ, যদি আপনি একটি হ্যান্ডল থেকে ফিরিয়ে দেওয়া না দিতে পারে GetModuleHandle
থেকে HeapDestroy
এবং এটি কিছু যুক্তিসম্মত করতে আশা।
HANDLE
নিজেই ঠিক অবিচ্ছেদ্য প্রকার। সাধারণত, তবে অগত্যা নয়, এটি কিছু অন্তর্নিহিত টাইপ বা মেমরির অবস্থানের জন্য একটি পয়েন্টার। উদাহরণস্বরূপ, HANDLE
ফিরে GetModuleHandle
আসাটি আসলে মডিউলটির বেস ভার্চুয়াল মেমরি ঠিকানার পয়েন্টার। তবে হ্যান্ডলগুলি পয়েন্টার হতে হবে বলে উল্লেখ করার কোনও নিয়ম নেই। একটি হ্যান্ডেলটি কেবল একটি সাধারণ পূর্ণসংখ্যা হতে পারে (যা সম্ভবত কিছু উইন 32 এপিআই ব্যবহার করতে পারে একটি অ্যারেতে সূচক হিসাবে)।
HANDLE
গুলি ইচ্ছাকৃত অস্বচ্ছ উপস্থাপনা যা অভ্যন্তরীণ উইন 32 সংস্থান থেকে এনক্যাপসুলেশন এবং বিমূর্ততা সরবরাহ করে। এইভাবে, উইন 32 এপিআইগুলি কোনওভাবেই হ্যান্ডল এর পিছনে অন্তর্নিহিত প্রকারটি পরিবর্তন করতে পারে, এটি কোনওভাবে ব্যবহারকারীর কোডকে প্রভাবিত না করে (কমপক্ষে এটি ধারণা)।
আমি সবেমাত্র তৈরি একটি উইন 32 এপিআইয়ের এই তিনটি পৃথক অভ্যন্তরীণ বাস্তবায়ন বিবেচনা করুন এবং ধরে নিন যে Widget
এটি একটি struct
।
Widget * GetWidget (std::string name)
{
Widget *w;
w = findWidget(name);
return w;
}
void * GetWidget (std::string name)
{
Widget *w;
w = findWidget(name);
return reinterpret_cast<void *>(w);
}
typedef void * HANDLE;
HANDLE GetWidget (std::string name)
{
Widget *w;
w = findWidget(name);
return reinterpret_cast<HANDLE>(w);
}
প্রথম উদাহরণটি এপিআই সম্পর্কে অভ্যন্তরীণ বিবরণ প্রকাশ করে: এটি ব্যবহারকারীর কোডটিকে এটি জানতে দেয় যে GetWidget
কোনওটিতে একটি পয়েন্টার দেয় struct Widget
। এর বেশ কয়েকটি পরিণতি ঘটেছে:
Widget
struct হয়Widget
কাঠামোর অভ্যন্তরীণ অংশগুলি সংশোধন করতে পারেএই উভয় পরিণতি অনাকাঙ্ক্ষিত হতে পারে।
দ্বিতীয় উদাহরণটি কেবলমাত্র ফিরে এসে ব্যবহারকারীর কোড থেকে এই অভ্যন্তরীণ বিবরণটি গোপন করে void *
। ব্যবহারকারীর Widget
কোডটির শিরোনামটিতে স্ট্রাকটি সংজ্ঞায়িত করার প্রয়োজন নেই ।
তৃতীয় উদাহরণটি হ'ল দ্বিতীয়টির মতো, তবে আমরা কেবল void *
একটি HANDLE
পরিবর্তে কল করি । সম্ভবত এটি ব্যবহারকারী কোডগুলিকে ঠিক কী void *
পয়েন্টগুলি বোঝায় তা নিরুৎসাহিত করে।
কেন এই ঝামেলা পার? এই একই API এর নতুন সংস্করণের এই চতুর্থ উদাহরণটি বিবেচনা করুন:
typedef void * HANDLE;
HANDLE GetWidget (std::string name)
{
NewImprovedWidget *w;
w = findImprovedWidget(name);
return reinterpret_cast<HANDLE>(w);
}
লক্ষ্য করুন যে ফাংশনটির ইন্টারফেসটি উপরের তৃতীয় উদাহরণের মতো। এর অর্থ এই যে ব্যবহারকারীর কোড কোনও পরিবর্তন ছাড়াই এপিআইয়ের এই নতুন সংস্করণটি ব্যবহার করা চালিয়ে যেতে পারে, যদিও "পর্দার অন্তরালে" প্রয়োগটি NewImprovedWidget
পরিবর্তে কাঠামো ব্যবহার করতে পরিবর্তিত হয়েছে ।
এই উদাহরণগুলির মধ্যে হ্যান্ডলগুলি আসলেই একটি নতুন, সম্ভবত বন্ধুত্বপূর্ণ void *
, যার নাম HANDLE
উইন 32 এপিআইতে রয়েছে ( এমএসডিএন এ দেখুন ) really এটি ব্যবহারকারীর কোড এবং উইন 32 লাইব্রেরির অভ্যন্তরীণ উপস্থাপনার মধ্যে একটি অস্বচ্ছ প্রাচীর সরবরাহ করে যা উইন্ডোজের সংস্করণগুলির মধ্যে, উইন 32 এপিআই ব্যবহার করে এমন কোডের, যা বহনযোগ্যতা বৃদ্ধি করে।
handle
পরিবর্তে void *
হয় ঠিক কি অকার্যকর * পয়েন্ট চিন্তা করার চেষ্টা থেকে নিরুৎসাহিত ব্যবহারকারী কোড । আমি কি সঠিক?
উইন 32 প্রোগ্রামিংয়ের একটি হ্যান্ডেল এমন একটি টোকেন যা উইন্ডোজ কার্নেল দ্বারা পরিচালিত এমন একটি সংস্থানকে উপস্থাপন করে। একটি হ্যান্ডেল উইন্ডো, একটি ফাইল ইত্যাদির হতে পারে etc.
হ্যান্ডলগুলি হ'ল উইন 32 এপিআইগুলি ব্যবহার করে আপনি যে কণাগুলি তৈরি করতে চান তা চিহ্নিত করার একটি উপায়।
সুতরাং উদাহরণস্বরূপ, আপনি যদি উইন্ডো তৈরি করতে চান এবং এটি স্ক্রিনে প্রদর্শন করতে চান তবে নিম্নলিখিতগুলি করতে পারেন:
// Create the window
HWND hwnd = CreateWindow(...);
if (!hwnd)
return; // hwnd not created
// Show the window.
ShowWindow(hwnd, SW_SHOW);
উপরের উদাহরণে এইচডাব্লুএনডি অর্থ "উইন্ডোতে একটি হ্যান্ডেল"।
যদি আপনি কোনও অবজেক্ট ওরিয়েন্টেড ল্যাঙ্গুয়েজে অভ্যস্ত হন তবে আপনি একটি হ্যান্ডেলকে এমন কোনও শ্রেণীর উদাহরণ হিসাবে ভাবতে পারেন যার কোনও পদ্ধতি নেই যার রাজ্যটি কেবল অন্য ফাংশন দ্বারা পরিবর্তনযোগ্য। এই ক্ষেত্রে শো উইন্ডো ফাংশনটি উইন্ডো হ্যান্ডেলের স্থিতি পরিবর্তন করে।
দেখুন পরিচালনা ও ডেটা প্রকার আরও তথ্যের জন্য।
HANDLE
ADT এর মাধ্যমে রেফারেন্সযুক্ত অবজেক্টগুলি কার্নেল দ্বারা পরিচালিত হয়। অন্যদিকে আপনি যে হ্যান্ডেল প্রকারের নাম ( HWND
ইত্যাদি) রাখেন সেগুলি হ'ল USER অবজেক্ট। এগুলি উইন্ডোজ কার্নেল দ্বারা পরিচালিত হয় না।
একটি হ্যান্ডেল উইন্ডোজ দ্বারা পরিচালিত কোনও সামগ্রীর জন্য একটি অনন্য শনাক্তকারী। এটি একটি পয়েন্টারের মতো , তবে এটি কোনও নির্দেশকের মতো নয় যে এটি কোনও ঠিকানা নয় যা ব্যবহারকারীর কোড দ্বারা কিছু ডেটাতে অ্যাক্সেস পাওয়ার জন্য বিবেচিত হতে পারে। পরিবর্তে একটি হ্যান্ডেল হ'ল হ্যান্ডেল সনাক্ত করে এমন বস্তুর ক্রিয়া সম্পাদন করতে পারে এমন ফাংশনগুলির একটি সংকেতে প্রেরণ করতে হবে।
সুতরাং সবচেয়ে বেসিক স্তরে যে কোনও ধরণের হ্যান্ডল হ'ল একটি পয়েন্টারকে নির্দেশক বা
#define HANDLE void **
এখন কেন আপনি এটি ব্যবহার করতে চান
একটি সেটআপ নিতে দেয়:
class Object{
int Value;
}
class LargeObj{
char * val;
LargeObj()
{
val = malloc(2048 * 1000);
}
}
void foo(Object bar){
LargeObj lo = new LargeObj();
bar.Value++;
}
void main()
{
Object obj = new Object();
obj.val = 1;
foo(obj);
printf("%d", obj.val);
}
সুতরাং যেহেতু আপত্তিটি মান দ্বারা পাস হয়েছিল (একটি অনুলিপি তৈরি করুন এবং এটি ফাংশনটিকে দিন) foo করার জন্য, মুদ্রণকারীটি 1 এর মূল মানটি মুদ্রণ করবে।
এখন আমরা যদি foo এ আপডেট করি:
void foo(Object * bar)
{
LargeObj lo = new LargeObj();
bar->val++;
}
এমন একটি সম্ভাবনা রয়েছে যা প্রিন্টফ 2 এর আপডেট হওয়া মানটি মুদ্রণ করবে তবে এমনও সম্ভাবনা রয়েছে যে ফু কিছুভাবে মেমরির দুর্নীতি বা ব্যতিক্রম ঘটায়।
কারণ আপনি যখন এখন 2 মেগা মেমরি বরাদ্দ করছেন সেই ফাংশনে আপত্তি পাস করার জন্য একটি পয়েন্টার ব্যবহার করছেন, এটি ওএসকে আপত্তিটির অবস্থান আপডেট করার জন্য মেমরিটিকে সরিয়ে ফেলতে পারে। যেহেতু আপনি মান দ্বারা পয়েন্টারটি পাস করেছেন, যদি আপত্তিটি সরানো হয় তবে ওএস পয়েন্টারটি আপডেট করে তবে ফাংশনে থাকা অনুলিপিটি না করে এবং সম্ভাব্য সমস্যা তৈরি করে।
এর চূড়ান্ত আপডেটের জন্য:
void foo(Object **bar){
LargeObj lo = LargeObj();
Object * b = &bar;
b->val++;
}
এটি সর্বদা আপডেট হওয়া মানটি মুদ্রণ করবে।
দেখুন, যখন সংকলক পয়েন্টারগুলির জন্য মেমরি বরাদ্দ করে এটি এগুলি স্থাবর হিসাবে চিহ্নিত করে, সুতরাং ফাংশনে পাস করা মান বরাদ্দ করা বড় অবজেক্টের কারণে মেমরির কোনও পুনর্বিবেচনা স্মৃতিতে চূড়ান্ত অবস্থানটি সন্ধানের জন্য সঠিক ঠিকানায় নির্দেশ করবে হালনাগাদ.
যে কোনও বিশেষ ধরণের হ্যান্ডেল (hWnd, ফাইল, ইত্যাদি) ডোমেইন নির্দিষ্ট এবং স্মৃতি দুর্নীতির বিরুদ্ধে সুরক্ষার জন্য নির্দিষ্ট ধরণের কাঠামোর দিকে নির্দেশ করে।
একটি হ্যান্ডেল একটি ডাটাবেসে রেকর্ডের প্রাথমিক কী মানের মতো।
সম্পাদনা 1: ভাল, ডাউন ডাউনটি কেন, একটি প্রাথমিক কী অনন্যভাবে একটি ডাটাবেস রেকর্ড সনাক্ত করে এবং উইন্ডোজ সিস্টেমের একটি হ্যান্ডেল একটি উইন্ডো, একটি খোলা ফাইল, ইত্যাদি স্বতন্ত্রভাবে চিহ্নিত করে, আমি যা বলছি তা তাই।
উইন্ডোটির উইন্ডোটিকে এমন স্ট্রাক হিসাবে বর্ণনা করুন যা এটি বর্ণনা করে। এই কাঠামোটি উইন্ডোজের অভ্যন্তরীণ অংশ এবং এটির বিশদ জানার দরকার নেই। পরিবর্তে, উইন্ডোজ সেই স্ট্রাক্টের জন্য পয়েন্টার গঠনের জন্য টাইপিডেফ সরবরাহ করে। এটি "হ্যান্ডেল" যার দ্বারা আপনি উইন্ডোতে ধরে রাখতে পারেন,