সি-তে, কিছু লোক পয়েন্টারটি মুক্ত করার আগে কেন ফেলে দেয়?


167

আমি একটি পুরানো কোড বেসে কাজ করছি এবং প্রায় বিনামূল্যে () এর প্রার্থনাটি তার যুক্তিতে একটি কাস্ট ব্যবহার করে। উদাহরণ স্বরূপ,

free((float *)velocity);
free((float *)acceleration);
free((char *)label);

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

এই ক্যাসেটগুলি ব্যবহার করার কোনও প্রযুক্তিগত কারণ আছে কি? এমনকি এগুলি ব্যবহার করার মতো কোনও বাস্তব কারণও আমি দেখতে পাচ্ছি না। তথ্য টাইপ মুক্ত করার আগে নিজেকে স্মরণ করিয়ে দেওয়ার কী দরকার?

সম্পাদনা: এই প্রশ্নটি অন্য প্রশ্নের সদৃশ নয় । অন্য প্রশ্নটি এই প্রশ্নের একটি বিশেষ ঘটনা, যা আমি মনে করি সুস্পষ্ট যদি নিকটতম ভোটাররা সমস্ত উত্তর পড়তেন।

কলোফন: আমি চেকমার্কটির "দৃ answer় উত্তর" দিচ্ছি কারণ এটি করার প্রয়োজন হতে পারে এটি একটি বিস্ময়কর আসল কারণ; তবে এটির পূর্ব-এএনএসআই সি প্রথা (কমপক্ষে কিছু প্রোগ্রামারদের মধ্যে) হওয়া সম্পর্কে উত্তরটি আমার ক্ষেত্রে এটি ব্যবহৃত হওয়ার কারণ বলে মনে হচ্ছে। এখানে অনেক লোকের দ্বারা প্রচুর ভাল পয়েন্ট। আপনার অবদানের জন্য আপনাকে ধন্যবাদ।


13
"ডাটা টাইপ মুক্ত করার আগে নিজেকে স্মরণ করিয়ে দেওয়ার কী লাভ?" হয়ত জানতে কত স্মৃতি মুক্ত হবে?
m0skit0

12
@ কোডার সংকলক ডিওলোকেশনটি করে না, অপারেটিং সিস্টেমটি করে।
m0skit0

20
@ m0skit0 "সম্ভবত কতটা স্মৃতি মুক্ত হবে তা জানতে?" প্রকারটি কতটা মুক্ত তা জানার দরকার নেই। সেই কারণে কাস্ট করা কেবলমাত্র খারাপ কোডিং।
ব্যবহারকারী 694733

9
@ এম0স্কিট0 পঠনযোগ্যতার জন্য Castালাই সর্বদা খারাপ কোডিং, কারণ castালাই পরিবর্তনগুলি কীভাবে ব্যাখ্যা করা হয় তা পরিবর্তন করে এবং এটি গুরুতর ত্রুটিগুলি আড়াল করে। যখন পাঠযোগ্যতার প্রয়োজন হয়, মন্তব্যগুলি আরও ভাল।
ব্যবহারকারী 694733

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

উত্তর:


171

পয়েন্টারগুলি থাকলে সংকলক সতর্কতাগুলি সমাধান করার জন্য কাস্টিংয়ের প্রয়োজন হতে পারে const। এখানে কোডের একটি উদাহরণ যা নিখরচায় আর্গুমেন্টটি না ফেলে সতর্কবার্তা তৈরি করে:

const float* velocity = malloc(2*sizeof(float));
free(velocity);

এবং সংকলক (জিসিসি 4.8.3) বলেছেন:

main.c: In function main’:
main.c:9:5: warning: passing argument 1 of free discards const qualifier from pointer target type [enabled by default]
     free(velocity);
     ^
In file included from main.c:2:0:
/usr/include/stdlib.h:482:13: note: expected void *’ but argument is of type const float *’
 extern void free (void *__ptr) __THROW;

আপনি যদি free((float*) velocity);সংকলকটি ব্যবহার করেন তবে অভিযোগ করা বন্ধ হয়ে যায়।


2
@ এম0স্কিট0 যা float*মুক্ত করার আগে কেউ কেন ঝুঁকে পড়ে তা ব্যাখ্যা করে না । আমি free((void *)velocity);জিসিসি ৪.৮.৩ দিয়ে চেষ্টা করেছি। অবশ্যই এটি কোনও প্রাচীন সংকলক
মনস নিকোলাইডিস

54
তবে কেন আপনার গতিশীলভাবে ধ্রুব মেমরি বরাদ্দ করা দরকার? আপনি এটি ব্যবহার করতে পারে না!
নীল_এম

33
@ নিলস_এম এটি একটি সরলীকৃত উদাহরণ যা বলতে পারেন। আমি কোনও ফাংশনে আসল কোডে যা করেছি তা হ'ল নন-কনস্ট্যান্ড মেমরি বরাদ্দ করা, মান নির্ধারণ করা, কনস্ট পয়েন্টারে কাস্ট করা এবং এটি ফিরিয়ে দেওয়া। এখন, পূর্বনির্ধারিত কনস্ট মেমরির জন্য একটি পয়েন্টার রয়েছে যে কাউকে মুক্ত করতে হবে।
মনোস নিকোলাইডিস

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

3
ভ্রান্ত, যদি কোনও ফাংশন const char *pআর্গুমেন্ট হিসাবে নেয় এবং তারপরে এটি মুক্ত করে, সঠিক কাজটি করা কাস্ট করা নয়pchar* বিনামূল্যে কাজ করার আগে । এটি এটিকে const char *pপ্রথম স্থানে নেওয়া হিসাবে ঘোষণা করার দরকার নেই , কারণ এটি পরিবর্তন করে *p এবং সেই অনুযায়ী ঘোষণা করা উচিত। (এবং যদি এটা const পয়েন্টার পরিবর্তে একটি const পয়েন্টার লাগে, int *const p, আপনি না প্রয়োজন ঢালাই যেহেতু এটা আসলে আইনি এবং এইভাবে ঢালাই ছাড়া কাজ করে জরিমানা।)
সত্যজিৎ

59

প্রাক-মান সি এর void*কেবলমাত্র ছিল না char*, সুতরাং আপনাকে সমস্ত পরামিতি পেরিয়ে যেতে হয়েছিল। যদি আপনি প্রাচীন সি কোড জুড়ে আসে, আপনি তাই এই জাতীয় ক্যাসেট খুঁজে পেতে পারেন।

রেফারেন্স সহ একই প্রশ্ন

প্রথম সি মান মুক্তি পায় malloc এবং বিনামূল্যে জন্য এগুলির নমুনা থাকার থেকে পরিবর্তিত char*করা void*তারা আজও আছে।

এবং অবশ্যই স্ট্যান্ডার্ড সিতে, এই জাতীয় কাস্টগুলি অতিশয় এবং কেবল পাঠযোগ্যতার ক্ষতি করে।


23
তবে আপনি কেন freeএকই ধরণের যুক্তিটি ইতিমধ্যে যেভাবে যুক্ত করবেন?
jwodder

4
@ chux প্রাক-মানক সমস্যাটি কেবল এটি: কোনও কিছুর জন্য কোনও বাধ্যবাধকতা নেই। লোকেরা কেবল ক্যাননের জন্য কেএন্ডআর বইয়ের দিকে ইঙ্গিত করেছিল কারণ এটাই ছিল তাদের কাছে। এবং আমরা কে ওআরআর দ্বিতীয় সংস্করণে বেশ কয়েকটি উদাহরণ থেকে দেখতে পাচ্ছি, কে ওআরআর নিজেরাই প্যারামিটারের ক্যাসেটগুলি কীভাবে freeস্ট্যান্ডার্ড সি তে কাজ করতে পারে তা সম্পর্কে আপনাকে বিভ্রান্ত করা হয়েছে (আপনাকে কাস্ট করার দরকার নেই)। আমি প্রথম সংস্করণটি পড়িনি তাই আমি বলতে পারি না যে তারা 80-এর প্রাক-মানকালেও বিভ্রান্ত হয়েছিল কিনা।
লন্ডিন

7
প্রাক-স্ট্যান্ডার্ড সি ছিল না void*, তবে এটিতে ফাংশন প্রোটোটাইপগুলিও নেই, সুতরাং যুক্তিটি যুক্ত করা freeএমনকি কে অ্যান্ডআর-তেও অপ্রয়োজনীয় ছিল (ধরে নিলেন যে সমস্ত ডেটা পয়েন্টার ধরণের একই উপস্থাপনা ব্যবহৃত হয়েছিল)।
ইয়ান অ্যাবট 16

6
ইতিমধ্যে মন্তব্যে বর্ণিত একাধিক কারণে, আমি মনে করি না যে এই উত্তরটি অর্থবোধ করে।
আর .. গীটহাব বন্ধ করুন ICE

4
আমি দেখতে পাচ্ছি না যে এই উত্তরটি কীভাবে প্রাসঙ্গিক কোনও কিছুর উত্তর দেবে। মূল প্রশ্নটি না শুধুমাত্র অন্যান্য ধরণের কাস্টকে জড়িত char *। পুরানো সংকলকগুলি ছাড়া এটি কী বোঝায় void? এই জাতীয় ক্যাসেটগুলি কী অর্জন করবে?
এন্ট

34

এখানে একটি উদাহরণ যেখানে বিনামূল্যে aালাই ব্যর্থ হবে:

volatile int* p = (volatile int*)malloc(5 * sizeof(int));
free(p);        // fail: warning C4090: 'function' : different 'volatile' qualifiers
free((int*)p);  // success :)
free((void*)p); // success :)

সি তে আপনি একটি সতর্কতা পেতে পারেন (ভিএস ২০১২ তে একটি পেয়েছেন)। সি ++ এ আপনি একটি ত্রুটি পাবেন।

বিরল মামলাগুলি বাদ দিয়ে কাস্টিংয়ে কেবল কোডটি ফুটিয়ে তোলে ...

সম্পাদনা: ব্যর্থতা ডেমো void*না int*করার জন্য আমি কাস্ট করেছি । এটি একইভাবে কাজ int*করবে যা void*ইমপ্লিটলি রূপান্তরিত হবে । যুক্ত int*কোড।


নোট করুন যে প্রশ্নটিতে পোস্ট করা কোডে, জঞ্জালগুলি নয় void *, তবে float *এবং তেমন char *। এই ক্যাসেটগুলি কেবল বহিরাগত নয়, তারা ভুল।
অ্যান্ড্রু হেনেল

1
প্রশ্নটি আসলে বিপরীত সম্পর্কে।
m0skit0

1
আমি উত্তর বুঝতে পারি না; কোন অর্থে free(p)ব্যর্থ হবে? এটি একটি সংকলক ত্রুটি দিতে হবে?
কোডার

1
এগুলি ভাল পয়েন্ট। constস্পষ্টতই, যোগ্যতা পয়েন্টারগুলির সাথে একই যায় ।
লন্ডিন

2
volatileসি দীর্ঘায়িত না হলে মানিককরণের পরে থেকে বিদ্যমান। এটি C99 এ যুক্ত করা হয়নি
আর .. গীটহাব বন্ধ করুন ICE

30

পুরানো কারণ: 1. ব্যবহার করে free((sometype*) ptr), কোডটি যে ধরণের নির্দেশককে free()কলটির অংশ হিসাবে বিবেচনা করা উচিত সে সম্পর্কে স্পষ্ট exp সুস্পষ্ট কাস্টটি কার্যকর free()( যখন এটি নিজে করুন) দিয়ে প্রতিস্থাপন করা হয় DIY_free()

#define free(ptr) DIY_free(ptr, sizeof (*ptr))

একজন DIY_free()ছিল (আছে) একটি উপায়, বিশেষ করে ডিবাগ মোডে, পয়েন্টার রান-টাইম বিশ্লেষণ মুক্ত হচ্ছে না। এটি প্রায়শই জরিমানা DIY_malloc(), বিশ্বব্যাপী মেমরি ব্যবহারের গণনা ইত্যাদি যুক্ত করার সাথে যুক্ত করা হয় My আরও আধুনিক সরঞ্জাম উপস্থিত হওয়ার আগে আমার গোষ্ঠী কয়েক বছর ধরে এই কৌশলটি ব্যবহার করেছিল। এটি বাধ্যতামূলক ছিল যে আইটেমটি ফ্রিড 'এ টাইপ করা হয়েছে তা মূলত বরাদ্দ করা হয়েছিল।

  1. মেমরির সমস্যাগুলি ট্র্যাক করে আনে এমন বেশ কয়েক ঘন্টা ব্যয় করা, ফ্রি'ড টাইপ কাস্ট করার মতো ছোট কৌশলগুলি ডিবাগটি অনুসন্ধান এবং সংকীর্ণ করতে সহায়তা করবে।

আধুনিক: মানস নিকোলাইডিস @ এবং @ ইগুর দ্বারা সম্বোধন করা এড়ানো constএবং volatileসতর্কতা । চিন্তাধারা আমি 3 প্রভাব নোট হবে কোয়ালিফায়ার : , , এবং ।constvolatilerestrict

[সম্পাদনা] char * restrict *rp2প্রতি @ আর .. মন্তব্য যুক্ত করা হয়েছে

void free_test(const char *cp, volatile char *vp, char * restrict rp, 
    char * restrict *rp2) {
  free(cp);  // warning
  free(vp);  // warning
  free(rp);  // OK
  free(rp2);  // warning
}

int main(void) {
  free_test(0,0,0,0);
  return 0;
}

3
restrictএটি যেখানে রাখা হয়েছে কেবলমাত্র একটি অ-ইস্যু - এটি rpপয়েন্ট-টু টাইপ না করে বস্তুকে প্রভাবিত করে । আপনার পরিবর্তে যদি থাকে char *restrict *rp, তবে এটি ব্যাপার হবে।
আর .. গীটহাব বন্ধ করুন ICE

16

এখানে আরেকটি বিকল্প অনুমান দেওয়া হল।

আমাদের বলা হয়েছে যে প্রোগ্রামটি সি -৮৯-এর পূর্বে লেখা হয়েছিল, যার অর্থ এটি প্রোটোটাইপের সাথে কোনওরকম অমিলের আশেপাশে কাজ করতে পারে না free, কারণ কেবল সি -৮৮ এর আগে যেমন ছিল constনা বা void *আগেও ছিল না, তেমন কিছুই ছিল না সি 98 এর আগে একটি ফাংশন প্রোটোটাইপstdlib.hনিজেই কমিটির আবিষ্কার ছিল। যদি সিস্টেমের শিরোনামগুলি freeএকেবারেই ঘোষণা করতে বিরত থাকে তবে তারা এটি এইভাবে করত:

extern free();  /* no `void` return type either! */

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

তবে এর অর্থ এখনও এই নয় যে freeবেশিরভাগ কেএন্ডআর সংকলকগুলিতে যুক্তিটি দেওয়া দরকার ছিল । মত একটি ফাংশন

free_stuff(a, b, c)
    float *a;
    char *b;
    int *c;
{
    free(a);
    free(b);
    free(c);
}

সঠিকভাবে সংকলন করা উচিত ছিল। সুতরাং আমি মনে করি আমরা এখানে যা পেয়েছি তা হ'ল একটি অস্বাভাবিক পরিবেশের জন্য বগি সংকলকটির সাথে লড়াই করার জন্য একটি প্রোগ্রাম লেখা: উদাহরণস্বরূপ, এমন একটি পরিবেশ যেখানে sizeof(float *) > sizeof(int)এবং সংকলকটি এটি করবে না পয়েন্টারগুলির জন্য উপযুক্ত কলিং কনভেনশন ব্যবহার যদি আপনি সেগুলিকে বিন্দুতে না ফেলে থাকেন কল এর।

আমি এই জাতীয় কোনও পরিবেশ সম্পর্কে সচেতন নই, তবে এর অর্থ এই নয় যে সেখানে একটিও ছিল না। সবচেয়ে সম্ভাব্য প্রার্থী যারা মাথায় আসে তারা হ'ল 1980 এর দশকের প্রথম দিকে 8- এবং 16-বিট মাইক্রোয়ের জন্য কাটা ডাউন "ছোট সি" সংকলক। শুরুর দিকে ক্রেসের এ জাতীয় সমস্যা ছিল তা জানতে পেরে আমি অবাক হব না।


1
প্রথমার্ধে আমি সম্পূর্ণরূপে একমত। এবং ২ য় অর্ধেকটি একটি উদ্বেগজনক এবং প্রশ্রয়দায়ক অনুমান।
chux - মনিকা পুনরায় স্থাপন করুন

9

প্যারামিটার হিসাবে নিখরচায় কেবল নন-কনস্ট্যান্ট পয়েন্টার নেয়। সুতরাং কনস্টেন্ট পয়েন্টারগুলির ক্ষেত্রে, একটি অ-কনস্ট্যান্ট পয়েন্টারে স্পষ্ট করে কাস্টিং প্রয়োজন।

সি তে কনস্ট পয়েন্টার মুক্ত করতে অক্ষম

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