আমি কখন সি তে ম্যালোক ব্যবহার করব এবং কখন করব না?


94

আমি বুঝতে পারি কীভাবে malloc () কাজ করে। আমার প্রশ্ন হ'ল আমি এই জাতীয় জিনিস দেখতে পাচ্ছি:

#define A_MEGABYTE (1024 * 1024)

char *some_memory;
size_t size_to_allocate = A_MEGABYTE;
some_memory = (char *)malloc(size_to_allocate);
sprintf(some_memory, "Hello World");
printf("%s\n", some_memory);
free(some_memory);

আমি সংক্ষিপ্ততার জন্য ত্রুটি পরীক্ষা করা বাদ দিয়েছি। আমার প্রশ্ন হ'ল আপনি কি স্মৃতিতে কিছু স্ট্যাটিক স্টোরেজটিতে পয়েন্টার শুরু করে উপরের কাজটি করতে পারবেন না? সম্ভবত:

char *some_memory = "Hello World";

আপনি যে মানগুলি বজায় রাখতে হবে তা ঘোষণার / আরম্ভ করার পরিবর্তে আপনাকে আসলে নিজেকে কী স্মৃতি বরাদ্দ করতে হবে?


5
পুনরায়: আমি সংক্ষিপ্ততার জন্য ত্রুটি পরীক্ষা করা বাদ দিয়েছি - দুর্ভাগ্যক্রমে অনেক প্রোগ্রামার ত্রুটি পরীক্ষা করা বাদ দেয় কারণ তারা বুঝতে malloc()পারেন না যে তারা ব্যর্থ হতে পারে!
অ্যান্ড্রু

উত্তর:


134
char *some_memory = "Hello World";

একটি স্ট্রিং ধ্রুবক একটি পয়েন্টার তৈরি করছে। তার মানে "হ্যালো ওয়ার্ল্ড" স্ট্রিংটি মেমরির কেবল পঠনযোগ্য অংশে কোথাও থাকবে এবং আপনার কাছে এটির একটি পয়েন্টার রয়েছে। আপনি স্ট্রিংটি কেবল পঠনযোগ্য হিসাবে ব্যবহার করতে পারেন। আপনি এতে পরিবর্তন করতে পারবেন না । উদাহরণ:

some_memory[0] = 'h';

ঝামেলা চাইছে।

অন্য দিকে

some_memory = (char *)malloc(size_to_allocate);

একটি বরাদ্দ করা হচ্ছে একটি অ্যারে (একটি ভেরিয়েবল) এবং কিছু বরাদ্দ মেমরির স্মৃতি পয়েন্ট points এখন এই অ্যারে পড়া এবং লেখার উভয়ই। আপনি এখন করতে পারেন:

some_memory[0] = 'h';

এবং অ্যারের সামগ্রীগুলি "হ্যালো ওয়ার্ল্ড" এ পরিবর্তিত হয়


19
কেবল পরিষ্কার করার জন্য, আমি এই উত্তরটি যতটা পছন্দ করি (আমি আপনাকে +1 দিয়েছিলাম), আপনি কেবলমাত্র একটি অক্ষরের অ্যারে ব্যবহার করে ম্যালোক () ছাড়াই এটি করতে পারেন। এরকম কিছু: Char some_memory [] = "হ্যালো"; some_memory [0] = 'ডাব্লু'; কাজ করবে।
এলোমেলোভাবে

19
আপনার ঠিক আছে। আপনি এটি করতে পারেন। আপনি যখন ম্যালোক ব্যবহার করেন () মেমরিটি চালুর সময় গতিশীলভাবে বরাদ্দ করা হয়, সুতরাং আপনাকে সঙ্কলনের সময় অ্যারের আকার ঠিক করতে হবে না আপনি পুনর্বিবেচনা ব্যবহার করে এটি বাড়িয়ে বা সঙ্কুচিত করতে পারবেন () এই জিনিসগুলির কোনও কিছুই করা যাবে না যখন আপনি করবেন: চর কিছু_মেমরি [] = "হ্যালো"; এখানে যদিও আপনি অ্যারের সামগ্রী পরিবর্তন করতে পারেন তবে এর আকারটি স্থির। সুতরাং আপনার প্রয়োজনের উপর নির্ভর করে আপনি তিনটি বিকল্পের মধ্যে যে কোনও একটি ব্যবহার করুন: 1) পয়েন্টার থেকে চর কনস্ট 2) গতিশীলভাবে বরাদ্দ করা অ্যারে 3) নির্দিষ্ট আকার, সময় বরাদ্দ করা অ্যারে সংকলন করুন।
কোডডডিক্ট

এটিকে কেবল পঠনযোগ্যতার উপর জোর দেওয়ার জন্য আপনার অবশ্যই লেখা উচিত এটি const char *s = "hi";কি স্ট্যান্ডার্ডের দ্বারা প্রয়োজনীয় নয়?
থিসিস

4
@ অবধি, না কারণ আপনি স্ট্রিং আক্ষরিক "হাই" এর মূল ঠিকানার পয়েন্টারটি প্রাথমিকভাবে ঘোষণা করেছিলেন। একটি নিরপেক্ষ চরকে নির্দেশ করার জন্য পুরোপুরি আইনীভাবে পুনরায় নিয়োগ করা যেতে পারে। আপনি যদি কেবল পঠনযোগ্য স্ট্রিংয়ের জন্য ধ্রুবক পয়েন্টার চান তবে আপনার প্রয়োজনconst char const* s;
রব 11311

38

সেই সঠিক উদাহরণের জন্য, malloc খুব কম ব্যবহার হয়।

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

একটি দ্বিতীয় কারণ হ'ল সি বরাদ্দ দেওয়ার জন্য স্ট্যাকের পর্যাপ্ত জায়গা রয়েছে কিনা তা জানার কোনও উপায় নেই। যদি আপনার কোডটি 100% শক্তিশালী হওয়া দরকার তবে ম্যালোক ব্যবহার করা নিরাপদ কারণ আপনার কোডটি বরাদ্দটি ব্যর্থ হতে পারে এবং এটি পরিচালনা করতে পারে।


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

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

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

@ Bob: এই দুষ্টু বাগগুলি, কনভেনশনটি করুন যে বরাদ্দকারী মেমরিটিকে আরও উন্নত করে দেয়, সর্বোপরি আপনি এটি পুনর্ব্যবহার করতে পারেন। ধরুন আপনি রেফারেন্সের স্থানীয়ত্ব উন্নত করতে কলোকের সাথে মেমরি বরাদ্দ করেছেন, যা সেই লাইব্রেরির ভাঙা প্রকৃতিটিকে উন্মোচিত করে, কারণ আপনাকে পুরো ব্লকের জন্য একবার একবার ফ্রি কল করতে হবে। ভাগ্যক্রমে আমাকে এমন লাইব্রেরি ব্যবহার করতে হয়নি যা মেমোরিটিকে 'ম্যালোক-এড' হিসাবে চিহ্নিত করে `এটি কোনও পসিক্স traditionতিহ্য নয় এবং সম্ভবত এটি একটি বাগ হিসাবে বিবেচিত হবে। যদি তারা "জানে" আপনাকে ম্যালোক ব্যবহার করতে হয় তবে লাইব্রেরির রুটিন আপনার জন্য এটি করে না কেন?
রব 11311

17

রানকালে মেমোরি বরাদ্দকরণ, পুনর্নির্মাণ এবং মেমরি মুক্ত করার জন্য মেলোক একটি দুর্দান্ত সরঞ্জাম, আপনার হ্যালো ওয়ার্ল্ড উদাহরণের মতো স্থির ঘোষণার তুলনায়, যা সংকলন সময়ে প্রক্রিয়া করা হয় এবং আকারে পরিবর্তন করা যায় না।

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

অবশ্যই, যেমনটি আপনি দিয়েছেন তার মতো তুচ্ছ উদাহরণে, ম্যালোক ম্যাজিকাল "সঠিক কাজের সঠিক সরঞ্জাম" নয়, আরও জটিল ক্ষেত্রে (উদাহরণস্বরূপ রানটাইমটিতে একটি স্বেচ্ছাকৃতির আকারের অ্যারে তৈরি করা), এটির একমাত্র উপায় যাওয়া.


7

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


সামান্য সামান্য অফ-টপিক, তবে ... আপনাকে ব্যবহার করার সময় মেমরি ফাঁস তৈরি না করার জন্য আপনাকে খুব যত্নবান হতে হবে malloc। এই কোডটি বিবেচনা করুন:

int do_something() {
    uint8_t* someMemory = (uint8_t*)malloc(1024);

    // Do some stuff

    if ( /* some error occured */ ) return -1;

    // Do some other stuff

    free(someMemory);
    return result;
}

আপনি কি দেখতে পান যে এই কোডটিতে কী সমস্যা আছে? তার মাঝে একটি শর্তাধীন প্রত্যাবর্তন বিবৃতি mallocএবং free। এটি প্রথমে ঠিক মনে হতে পারে তবে এটি সম্পর্কে চিন্তা করুন। যদি কোনও ত্রুটি হয় তবে আপনি বরাদ্দ করা মেমরিটি ছাড়াই আপনি ফিরে যাচ্ছেন। এটি মেমরি ফাঁসের একটি সাধারণ উত্স।

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

সুতরাং আপনি যখনই ব্যবহার করবেন malloc, সর্বদা নিশ্চিত করুন যে আপনার মেমরিটি freeযতটা সম্ভব সম্ভব be


দুর্দান্ত উদাহরণ! যাওয়ার উপায় ^ _ ^
মূসা আল-হাসি

6
char *some_memory = "Hello World";
sprintf(some_memory, "Goodbye...");

অবৈধ, স্ট্রিং আক্ষরিক হয় const

এটি স্ট্যাক বা বিশ্বব্যাপী (এটি কোথায় ঘোষিত হয়েছে তার উপর নির্ভর করে) একটি 12-বাইটের চর অ্যারে বরাদ্দ করবে।

char some_memory[] = "Hello World";

আপনি যদি আরও হেরফেরের জন্য ঘর ছেড়ে যেতে চান তবে আপনি উল্লেখ করতে পারেন যে অ্যারেটি আরও বড় আকারের হওয়া উচিত। (তবে স্ট্যাকের উপরে 1 এমবি রাখবেন না।)

#define LINE_LEN 80

char some_memory[LINE_LEN] = "Hello World";
strcpy(some_memory, "Goodbye, sad world...");
printf("%s\n", some_memory);

5

মেমরি বরাদ্দ করার প্রয়োজন হওয়ার একটি কারণ আপনি যদি রানটাইমটিতে এটি পরিবর্তন করতে চান। সেক্ষেত্রে স্ট্যাকের কোনও ম্যালোক বা একটি বাফার ব্যবহার করা যেতে পারে। কোনও পয়েন্টারের কাছে "হ্যালো ওয়ার্ল্ড" অর্পণের সহজ উদাহরণটি মেমরির সংজ্ঞা দেয় যে রানটাইমে "সাধারণত" পরিবর্তন করা যায় না।

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