সি-এ [বন্ধ] এপিআই ডিজাইনের ক্ষতি


10

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

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

যদিও এই প্রশ্নের কেন্দ্রবিন্দু সি এপিআই, আপনার অন্যান্য ভাষায় এগুলি ব্যবহারের আপনার ক্ষমতাকে প্রভাবিত করে এমন সমস্যাগুলি স্বাগত।

অনুগ্রহ করে উত্তর প্রতি একটি ত্রুটি দিন, যাতে গণতন্ত্র উত্তরগুলি বাছাই করতে পারে।


3
জো, এই প্রশ্নটি লোকেদের ঘৃণিত জিনিসের একটি তালিকা তৈরি করতে বলে অনুরোধ করে গঠনমূলক না হওয়ার বিষয়ে প্রশ্ন তুলছে। উত্তরগুলি কেন তারা নির্দেশ করছে যে অনুশীলনগুলি খারাপ তা ব্যাখ্যা করে এবং কীভাবে সেগুলি উন্নত করা যায় সে সম্পর্কে বিশদ তথ্য সরবরাহ করে যদি প্রশ্নগুলির কার্যকর হওয়ার সম্ভাবনা রয়েছে । সে লক্ষ্যে, দয়া করে প্রশ্ন থেকে আপনার উদাহরণটি তার নিজের উত্তরে সরিয়ে নিন এবং ব্যাখ্যা করুন কেন এটি সমস্যা / কীভাবে একটি malloc'স্ট্রিং এটি ঠিক করবে would আমি মনে করি প্রথম উত্তর দিয়ে একটি ভাল উদাহরণ স্থাপন সত্যিই এই প্রশ্নে সাফল্য লাভ করতে পারে। ধন্যবাদ!
আদম লিয়ার

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

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

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

উত্তর:


5

অসামঞ্জস্যপূর্ণ বা অযৌক্তিক রিটার্ন মান সহ ফাংশন। দুটি ভাল উদাহরণ:

1) কিছু উইন্ডো ফাংশন যা একটি হ্যান্ডেল ফিরে আসে একটি ত্রুটির জন্য (নোট) তৈরি করতে NULL / 0 ব্যবহার করে, কিছু INVALID_HANDLE_VALUE / -1 ব্যবহার করে একটি ত্রুটি (ক্রিয়েটফিল) ব্যবহার করে।

২) পসিএক্স 'টাইম' ফাংশনটি ত্রুটির সাথে '(সময়_ টি) -১' দেয় যা সত্যই অযৌক্তিক যেহেতু 'টাইম_টি' হয় স্বাক্ষরিত বা স্বাক্ষরবিহীন প্রকার হতে পারে।


2
প্রকৃতপক্ষে, সময়_টি (সাধারণত) স্বাক্ষরিত হয়। তবে, 31 ডিসেম্বর, 1969 "অবৈধ" কল করা অযৌক্তিক। আমার ধারণা 60 এর দশকটি মোটামুটি ছিল :-) গম্ভীরতার সাথে একটি সমাধান হতে পারে ত্রুটি কোডটি ফেরত দেওয়া, এবং ফলাফলটি একটি পয়েন্টারের মাধ্যমে দিয়ে দেওয়া, যেমন: int time(time_t *out);এবং BOOL CreateFile(LPCTSTR lpFileName, ..., HANDLE *out);
জোয়ে অ্যাডামস

যথাযথভাবে। যদি time_t স্বাক্ষরবিহীন হয় এটা অদ্ভুত, এবং যদি time_t স্বাক্ষরিত হয়, এটি তোলে এক বৈধ বেশী একজন সমুদ্রের মাঝখানে সময় অবৈধ।
ডেভিড শোয়ার্জ

4

অ-বর্ণনামূলক বা নিশ্চিতভাবে বিভ্রান্তিকর নামের সাথে ফাংশন বা পরামিতি। উদাহরণ স্বরূপ:

1) ক্রিয়েটফিল, উইন্ডোজ এপিআইতে আসলে কোনও ফাইল তৈরি করে না, এটি একটি ফাইল হ্যান্ডেল তৈরি করে। এটি যদি কোনও প্যারামিটারের মাধ্যমে জিজ্ঞাসা করা হয় তবে 'ওপেন' ক্যানের মতো একটি ফাইল তৈরি করতে পারে। এই প্যারামিটারটির 'CREATE_ALWAYS' এবং 'CREATE_NEW' নামক মান রয়েছে যার নামগুলি তাদের শব্দার্থবিজ্ঞানে এমনকি ইঙ্গিত দেয় না। ('CREATE_ALWAYS' এর অর্থ ফাইলটি বিদ্যমান থাকলে এটি ব্যর্থ হয়? বা এর উপরে একটি নতুন ফাইল তৈরি করে? 'CREATE_NEW' এর অর্থ এটি সর্বদা একটি নতুন ফাইল তৈরি করে এবং যদি ফাইলটি ইতিমধ্যে বিদ্যমান থাকে তবে ব্যর্থ হয়? বা এটি একটি নতুন তৈরি করে? এর উপরে ফাইল?)

2) পসিক্স প্যাথ্রেডস এপিআই-এ pthread_cond_wait, এটির নাম থাকা সত্ত্বেও এটি একটি শর্তহীন অপেক্ষা।


1
Cond মধ্যে pthread_cond_waitমানে এই নয় "শর্তসাপেক্ষে অপেক্ষা করুন"। এটি আপনাকে শর্ত পরিবর্তনশীলের জন্য অপেক্ষা করছে এই বিষয়টি বোঝায় ।
জোনাথন রাইনহার্ট

ঠিক আছে, এটি একটি শর্তের জন্য নিঃশর্ত অপেক্ষা ।
ডেভিড শোয়ার্জ

3

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

এটি বিভিন্ন রূপ এবং স্বাদে আসে, যার মধ্যে রয়েছে তবে সীমাবদ্ধ নয়:

  • void* অপব্যবহার

  • intরিসোর্স হ্যান্ডেল হিসাবে ব্যবহার করা (উদাহরণস্বরূপ: সিডিআই লাইব্রেরি)

  • স্টোরলি আর্গুমেন্ট টাইপ

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

typedef struct Foo Foo;
typedef struct Bar Bar;

Foo* createFoo();
Bar* createBar();

int doSomething(Foo* foo);
void somethingElse(Foo* foo, Bar* bar);

void destroyFoo(Foo* foo);
void destroyBar(Bar* bar);

2

অসামঞ্জস্যপূর্ণ এবং প্রায়শই জটিল স্ট্রিং রিটার্নিং কনভেনশনগুলির সাথে ফাংশন।

উদাহরণস্বরূপ, getcwd একটি ব্যবহারকারী সরবরাহিত বাফার এবং এর আকারের জন্য জিজ্ঞাসা করে। এর অর্থ একটি অ্যাপ্লিকেশনকে হয় বর্তমান ডিরেক্টরি দৈর্ঘ্যের উপর একটি স্বেচ্ছাচারী সীমা নির্ধারণ করতে হবে, বা এই জাতীয় কিছু করতে হবে ( সিসিএএন থেকে ):

 /* *This* is why people hate C. */
len = 32;
cwd = talloc_array(ctx, char, len);
while (!getcwd(cwd, len)) {
    if (errno != ERANGE) {
        talloc_free(cwd);
        return NULL;
    }
    cwd = talloc_realloc(ctx, cwd, char, len *= 2);
}

আমার সমাধান: একটি mallocএড স্ট্রিং ফিরিয়ে দিন । এটি সহজ, শক্তিশালী এবং কম দক্ষ নয়। এম্বেড থাকা প্ল্যাটফর্ম এবং পুরানো সিস্টেম mallocব্যতীত আসলে বেশ দ্রুত।


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

@ লন্ডিন: সমস্যাটি হ'ল এটি প্রোগ্রামারগুলিকে অপ্রয়োজনীয় হার্ড-কোডেড সীমা তৈরি করার দিকে পরিচালিত করে এবং তাদেরকে (উপরের উদাহরণটি দেখুন) না করার জন্য সত্যই চেষ্টা করতে হবে। snprintf(buf, 32, "%d", n)যেমন আউটপুট দৈর্ঘ্য অনুমানযোগ্য ( intযেমন আপনার সিস্টেমে সত্যই বিশাল না হয় 30 এর বেশি না) যেমন জিনিসগুলির জন্য এটি দুর্দান্ত fine প্রকৃতপক্ষে, বহু সিস্টেমে malloc উপলভ্য নয়, তবে ডেস্কটপ এবং সার্ভার পরিবেশের জন্য, এটি রয়েছে এবং এটি সত্যিই ভালভাবে কাজ করে।
জোয় অ্যাডামস

তবে সমস্যাটি হ'ল আপনার উদাহরণের ফাংশনটি কোনও হার্ড-কোডড সীমা নির্ধারণ করে না। এর মতো কোডটি সাধারণ অনুশীলন নয়। এখানে, প্রধানগুলি ফাংশনটি জানা উচিত ছিল এমন বাফার দৈর্ঘ্য সম্পর্কে জিনিসগুলি জানে। এটি সবই প্রোগ্রামের দুর্বল নকশার পরামর্শ দেয়। মেইন getcwd ফাংশন এমনকি কী করে তা জানে বলে মনে হয় না, তাই এটি অনুসন্ধানের জন্য কিছু "ব্রুট ফোর্স" বরাদ্দ ব্যবহার করছে। কোথাও মডিউলটির মধ্যে ইন্টারফেস যেখানে getcwd থাকে এবং কলার কেটে যায় udd এর অর্থ এই নয় যে কলিং ফাংশনগুলির এই উপায়টি খারাপ, বিপরীত অভিজ্ঞতাটি দেখায় যে আমি ইতিমধ্যে তালিকাভুক্ত করার কারণে এটি ভাল।

1

ক্রিয়াকলাপগুলি মান অনুসারে যৌগিক ডেটা টাইপ করে / ফেরত দেয় বা কলব্যাকগুলি ব্যবহার করে।

আরও খারাপ যদি বলা হয় যে টাইপটি একটি ইউনিয়ন বা বিট-ফিল্ড রয়েছে।

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

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