"স্ট্রাক হ্যাক" প্রযুক্তিগতভাবে অপরিবর্তিত আচরণ?


111

আমি যা সম্পর্কে জিজ্ঞাসা করছি তা হ'ল সুপরিচিত "কাঠামোর সর্বশেষ সদস্যের পরিবর্তনশীল দৈর্ঘ্য" কৌশলটি। এইটার মতো কিছু একটা হচ্ছে:

struct T {
    int len;
    char s[1];
};

struct T *p = malloc(sizeof(struct T) + 100);
p->len = 100;
strcpy(p->s, "hello world");

স্ট্রাক্টটি মেমোরিতে যেভাবে সাজানো হয়েছে তার কারণে আমরা স্ট্রাক্টটিকে প্রয়োজনীয় ব্লকের চেয়ে বৃহত্তর উপরে ওভারলে করতে সক্ষম হয়েছি এবং শেষ সদস্যকে যেমন 1 charনির্দিষ্টর চেয়ে বড় তার সাথে আচরণ করতে পারি ।

সুতরাং প্রশ্নটি হল: এই কৌশলটি কি প্রযুক্তিগতভাবে অপরিবর্তিত আচরণ? । আমি আশা করব এটি হ'ল, তবে এই সম্পর্কে মান কী বলেছিল তা আগ্রহী ছিল।

PS: আমি এটি সম্পর্কে C99 পদ্ধতির বিষয়ে সচেতন, আমি উত্তরগুলি উপরে তালিকাভুক্ত হিসাবে কৌশলটির সংস্করণটিতে বিশেষভাবে আটকে রাখতে চাই।


33
এটি বেশ পরিষ্কার, যুক্তিসঙ্গত এবং সর্বোপরি উত্তরযোগ্য প্রশ্নের মতো মনে হচ্ছে । কাছের ভোটের কারণ দেখছেন না।
সিএইচও

2
যদি আপনি এমন একটি "আনসি সি" সংকলক প্রবর্তন করেন যা স্ট্রাক হ্যাক সমর্থন করে না, তবে বেশিরভাগ সি প্রোগ্রামাররা আমি জানি যে আপনার সংকলক "সঠিকভাবে কাজ করেছেন" তা গ্রহণ করবে না। তারা স্ট্যান্ডার্ডের কঠোর পাঠ গ্রহণ করবে তা প্রতিরোধ করে না। কমিটি কেবল এটিতে একটি মিস করে।
ডিএমকেকে --- প্রাক্তন মডারেটর বিড়ালছানা

4
@ জেমস হ্যাক একটি ন্যূনতম অ্যারে ঘোষণা করা সত্ত্বেও আপনার অর্থের অ্যারের জন্য যথেষ্ট পরিমাণে কোনও বস্তুটিকে ম্যালোক করে কাজ করে। সুতরাং আপনি কাঠামোর কঠোর সংজ্ঞা বাইরে বরাদ্দ মেমরি অ্যাক্সেস করা হয় । আপনার বরাদ্দ অতীতের লিখন একটি ভুল দায়িত্বহীন, তবে এটি আপনার বরাদ্দে লেখার চেয়ে আলাদা তবে "কাঠামোর" বাইরে।
ডিএমকেকে --- প্রাক্তন মডারেটর বিড়ালছানা

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

5
@ ডিটলি: দুটি জিনিস বরাদ্দ / ডিএলোকট করার চেয়ে একটি বিষয় বরাদ্দ করা / ডিএলোকট করা সহজ, বিশেষত যেহেতু আপনার সাথে মোকাবিলা করার জন্য ব্যর্থ হওয়ার দুটি উপায় রয়েছে। এটি আমার কাছে প্রান্তিক ব্যয় / গতির সাশ্রয়ের চেয়ে বেশি গুরুত্বপূর্ণ।
জেমসডলিন

উত্তর:


52

সি এফকিউ যেমন বলেছে:

এটি আইনী বা পোর্টেবল কিনা তা পরিষ্কার নয় তবে এটি জনপ্রিয় popular

এবং:

... একটি সরকারী ব্যাখ্যায় ধারণা করা হয়েছে যে এটি সি স্ট্যান্ডার্ডের সাথে কঠোরভাবে মেনে চলছে না, যদিও এটি সমস্ত পরিচিত বাস্তবায়নের অধীনে কাজ করে বলে মনে হচ্ছে। (সাবধানে অ্যারে সীমানা যাচাই করে এমন সংকলকরা সতর্কতা জারি করতে পারে))

'কঠোরভাবে মেনে চলার ' বিটের পিছনে যুক্তিটি অনুচ্ছেদে রয়েছে , বিভাগ J.2 অপরিজ্ঞাত আচরণ , যা অপরিজ্ঞাত আচরণের তালিকায় অন্তর্ভুক্ত রয়েছে:

  • একটি অ্যারের সাবস্ক্রিপ্ট সীমার বাইরে নয়, এমনকি যদি কোনও বস্তু প্রদত্ত সাবস্ক্রিপ্টের সাথে দৃশ্যত অ্যাক্সেসযোগ্য হয় (যেমন a[1][7]ঘোষণার প্রদত্ত লভ্য অভিব্যক্তিতে রয়েছে int a[4][5]) ( .5..6..6 )।

বিভাগ 6.5.6 এর 8 অনুচ্ছেদে অ্যাডিটিভ অপারেটরগুলির মধ্যে আরও একটি উল্লেখ রয়েছে যে সংজ্ঞায়িত অ্যারে সীমা ছাড়িয়ে অ্যাক্সেস অপরিজ্ঞাত:

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


1
ওপির কোডে p->sকখনও অ্যারে হিসাবে ব্যবহৃত হয় না। এটি এর মধ্যে চলে গেছে strcpy, এক্ষেত্রে এটি একটি সমভূমিতে স্থির হয়ে যায় char *, যা এমন কোনও বস্তুর দিকে ইঙ্গিত করে যা আইনতভাবে char [100];বরাদ্দকৃত বস্তুর অভ্যন্তরের হিসাবে ব্যাখ্যা করা যায় ।
আর .. গীটহাব বন্ধ করুন ICE

3
সম্ভবত এটি দেখার অন্য একটি উপায় হ'ল ভাষাটি আপনি জে .২-তে বর্ণিত হিসাবে প্রকৃত অ্যারে ভেরিয়েবলগুলিতে কীভাবে অ্যাক্সেস করতে পারবেন তা সীমাবদ্ধ করতে পারে , তবে আপনি কেবলমাত্র ফেরতকে mallocরূপান্তরিত করার পরে কোনও বরাদ্দকৃত বস্তুর জন্য এ জাতীয় বিধিনিষেধ তৈরি করার কোনও উপায় নেই when void *একটি অ্যারে [একটি কাঠামো] একটি পয়েন্টার। এটি এখনও পয়েন্টার ব্যবহার করে char(বা পছন্দসই unsigned char) বরাদ্দকৃত অবজেক্টের কোনও অংশ অ্যাক্সেস করার জন্য বৈধ ।
আর .. গীটহাব বন্ধ করুন ICE

@R। - আমি দেখতে পাচ্ছি কীভাবে জে 2 এটি কভার করতে পারে না তবে এটি কি 6.5.6 দ্বারাও আচ্ছাদিত নয়?
অবধি

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

4
অবজেক্টটি অ্যারে অবজেক্ট নয় তাই .5.৫..6 অপ্রাসঙ্গিক। অবজেক্টটি বরাদ্দকৃত মেমরির ব্লক malloc। বিএস বন্ধ করার আগে স্ট্যান্ডার্ডে "অবজেক্ট" সন্ধান করুন।
আর .. গীটহাব বন্ধ করুন ICE

34

আমি বিশ্বাস করি যে প্রযুক্তিগতভাবে এটি অপরিবর্তিত আচরণ। মানক (তর্কযোগ্যভাবে) এটি সরাসরি সম্বোধন করে না, তাই এটি "বা আচরণের কোনও সুস্পষ্ট সংজ্ঞা বাদ দিয়ে" এর অধীনে আসে। ধারা (সি 99 এর §4 / 2, সি 98 এর .13.16 / 2) এটির অপরিবর্তিত আচরণ বলে।

উপরে "তর্কযুক্ত" অ্যারে সাবস্ক্রিপ্টিং অপারেটরের সংজ্ঞা উপর নির্ভর করে। বিশেষত, এটি বলে: "একটি পোস্টফিক্স এক্সপ্রেশন যার পরে বর্গাকার বন্ধনীগুলিতে একটি এক্সপ্রেশন হয় []] একটি অ্যারে অবজেক্টের সাবস্ক্রিপশনযুক্ত উপাধি" " (সি 89, §6.3.2.1 / 2)।

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

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


2
আমি এমন একটি সংকলক কল্পনাও করতে পারি যা সিদ্ধান্ত নিতে পারে যে অ্যারেটি যদি 1 মাপের আকারের হয়ে থাকে, তবে arr[x] = y;এটি আবার লিখতে পারে arr[0] = y;; আকার 2 এর অ্যারের জন্য, arr[i] = 4;আবার লেখা যেতে পারে কারণ i ? arr[1] = 4 : arr[0] = 4; আমি কখনই কোনও সংকলককে এ জাতীয় অনুকূলকরণ সম্পাদন করতে দেখিনি, কিছু এম্বেড থাকা সিস্টেমে তারা খুব উত্পাদনশীল হতে পারে। একটি PIC18x- এ, 8-বিট ডেটা টাইপ ব্যবহার করে, প্রথম বিবৃতিটির কোডটি হবে ষোল বাইট, দ্বিতীয়, দুই বা চার এবং তৃতীয়, আট বা বারো। আইনী হলে খারাপ অপ্টিমাইজেশন নয়।
সুপারক্যাট

মান যদি অ্যারে সীমানার বাইরে অ্যারে অ্যাক্সেসকে সংজ্ঞায়িত আচরণ হিসাবে সংজ্ঞায়িত করে, তবে স্ট্রাক হ্যাকটিও খুব বেশি। তবে, মানক নির্দেশক গাণিতিক ( a[2] == a + 2) এর জন্য অ্যারে অ্যাক্সেসকে সিনট্যাকটিকাল চিনির হিসাবে সংজ্ঞায়িত করে, এটি হয় না। আমি যদি সঠিক হয় তবে সমস্ত সি স্ট্যান্ডার্ড অ্যারে অ্যাক্সেসকে পয়েন্টার গাণিতিক হিসাবে সংজ্ঞায়িত করে।
yyny

13

হ্যাঁ, এটি অনির্ধারিত আচরণ।

সি ল্যাঙ্গুয়েজ ত্রুটি রিপোর্ট # 051 এই প্রশ্নের একটি সঠিক উত্তর দেয়:

প্রচলিত আইডিয়োম, যদিও সাধারণ, তা কঠোরভাবে মেনে চলছে না

http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_051.html

সি 99 যুক্তির নথিতে সি কমিটি যুক্ত করেছে:

এই নির্মাণের বৈধতা সর্বদা প্রশ্নবিদ্ধ। একটি ত্রুটিপূর্ণ প্রতিবেদনের প্রতিক্রিয়ায়, কমিটি সিদ্ধান্ত নিয়েছে যে এটি অপরিজ্ঞাত আচরণ ছিল কারণ অ্যারে পি-> আইটেমগুলিতে কেবল একটি আইটেম রয়েছে, স্থান নির্ধারিত কিনা তা নির্বিশেষে।


2
এটি সন্ধানের জন্য +1, তবে আমি এখনও এটি স্ববিরোধী বলে দাবি করি। একই বস্তুর দুটি পয়েন্টার (এই ক্ষেত্রে, প্রদত্ত বাইট) সমান, এবং এটির জন্য একটি পয়েন্টার (প্রাপ্ত সামগ্রীর উপস্থাপনের অ্যারেতে পয়েন্টার malloc) সংযোজনে বৈধ, সুতরাং কীভাবে অভিন্ন পয়েন্টার, অন্য রুটের মাধ্যমে প্রাপ্ত, যোগটি অবৈধ হতে হবে? এমনকি তারা এটির ইউবি দাবি করতে চাইলেও এটি বেশ অর্থহীন, কারণ সুসংজ্ঞাত ব্যবহার এবং অনুমিত-সংজ্ঞায়িত ব্যবহারের মধ্যে পার্থক্য করার জন্য গণনার কোনও উপায় নেই।
আর .. গীটহাব

এটি খুব খারাপ যে সি সংকলনকারীরা শূন্য দৈর্ঘ্যের অ্যারে ঘোষণা নিষিদ্ধ করা শুরু করেছিল; যদি এটি নিষেধাজ্ঞার পক্ষে না হয়, তবে অনেক সংকলককে তাদের "উচিত" হিসাবে কাজ করার জন্য কোনও বিশেষ হ্যান্ডলিংয়ের দরকার পড়েনি, তবে তবুও তারা একক-উপাদান অ্যারেগুলির জন্য বিশেষ-ক্ষেত্রে কোড সক্ষম করতে সক্ষম হতেন (যেমন যদি *fooএকটি থাকে একক-উপাদান অ্যারে boz, এক্সপ্রেশন foo->boz[biz()*391]=9;হিসাবে সরলীকৃত হতে পারে biz(),foo->boz[0]=9;)। দুর্ভাগ্যক্রমে, সংকলকগুলির প্রত্যাখ্যান শূন্য-উপাদান অ্যারে মানে প্রচুর কোড পরিবর্তে একক-উপাদান অ্যারে ব্যবহার করে এবং সেই অপ্টিমাইজেশনের দ্বারা ভেঙে যায়।
সুপারক্যাট

11

এটি করার সেই বিশেষ পদ্ধতিটি কোনও সি স্ট্যান্ডার্ডে স্পষ্টভাবে সংজ্ঞায়িত করা হয়নি, তবে সি 99 ভাষার অংশ হিসাবে "স্ট্রাক হ্যাক" অন্তর্ভুক্ত করে। C99-এ, কাঠামোর শেষ সদস্যটি "নমনীয় অ্যারে সদস্য" হতে পারে, হিসাবে ঘোষিত char foo[](আপনার জায়গায় যে প্রকারের সাথে ইচ্ছা তেমন char)।


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

7

এটি যে কোনও, আধিকারিক বা অন্য যেভাবেই বলুক না কেন, এটি অপরিবর্তিত আচরণ নয় , কারণ এটি স্ট্যান্ডার্ড দ্বারা সংজ্ঞায়িত হয়। p->s, যখন একটি ল্যাভেলু হিসাবে ব্যবহৃত হয় ব্যতীত, অনুরূপ পয়েন্টারের সাথে মূল্যায়ন করে (char *)p + offsetof(struct T, s)। বিশেষত, charএটি malloc'd অবজেক্টের ভিতরে একটি বৈধ পয়েন্টার এবং এর সাথে সাথে অনুসরণ করা 100 টি (বা আরও বেশি, প্রান্তিককরণ বিবেচনার উপর নির্ভরশীল) একের পর এক ঠিকানা রয়েছে যা charবরাদ্দকৃত বস্তুর অভ্যন্তরের অবজেক্ট হিসাবে বৈধ । সত্য যে পয়েন্টার ব্যবহার করে উদ্ভূত হয়েছিল ->পরিবর্তে স্পষ্টভাবে যোগ পয়েন্টার দ্বারা ফিরে যাও অফসেট malloc, কাস্ট char *, অপ্রাসঙ্গিক।

টেকনিক্যালি, p->s[0]একক উপাদান charstruct ভিতরে এরে, আগামী কয়েক উপাদান (যেমন p->s[1]মাধ্যমে p->s[3]) সম্ভবত প্যাডিং struct হয়, যা আপনি একটি সম্পূর্ণ struct যাও নিয়োগ সঞ্চালন বিকৃত হতে পারে কিন্তু যদি ভিতরে বাইট আপনি নিছক এক্সেস পৃথক সদস্যগণ এবং বাকী উপাদানগুলি বরাদ্দ হওয়া অবজেক্টে অতিরিক্ত স্থান যা আপনি পছন্দ করতে পারেন তবে আপনার পছন্দ মতো, যতক্ষণ আপনি প্রান্তিককরণের প্রয়োজনীয়তা মানেন (এবং charকোনও প্রান্তিককরণের প্রয়োজনীয়তা নেই)।

আপনি চিন্তিত যে প্যাডিং সহ ওভারল্যাপিং সম্ভাবনা struct হয় বাইট একরকম অনুনাসিক ভূত ডাকা, আপনি প্রতিস্থাপন করে এই এড়াতে পারে হতে পারে তবে 1[1]যা নিশ্চিত করে struct হয় শেষে কোনো প্যাডিং আছে একটি মান সঙ্গে। এটি করার একটি সহজ কিন্তু অপ্রয়োজনীয় উপায় হ'ল শেষে কোনও অ্যারে বাদে অভিন্ন সদস্যদের সাথে একটি কাঠামো তৈরি করা এবং s[sizeof struct that_other_struct];অ্যারের জন্য ব্যবহার করা। তারপরে, p->s[i]স্ট্রাক্টের জন্য অ্যারের উপাদান হিসাবে এবং কাঠামোর i<sizeof struct that_other_structশেষের পরে কোনও ঠিকানায় একটি চর অবজেক্ট হিসাবে স্পষ্টভাবে সংজ্ঞায়িত করা হয় i>=sizeof struct that_other_struct

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

সম্পাদনা 2: প্যাডিং বাইট সহ ওভারল্যাপটি স্ট্যান্ডার্ডের অন্য অংশের কারণে অবশ্যই সমস্যা নয়। সি প্রয়োজন হয় যে যদি দুটি স্ট্রাক্ট তাদের উপাদানগুলির প্রাথমিক অনুচ্ছেদে সম্মত হয় তবে সাধারণ প্রাথমিক উপাদানগুলি উভয় প্রকারে পয়েন্টারের মাধ্যমে অ্যাক্সেস করা যায়। ফলত, যদি একটি struct অভিন্ন struct Tকিন্তু একটি বৃহত্তর চূড়ান্ত অ্যারে ঘোষিত হয়েছে, উপাদান s[0]উপাদান সঙ্গে কাকতালীয়ভাবে করতে হবে s[0]সালে struct T, এবং এই অতিরিক্ত উপাদানের উপস্থিতি প্রভাবিত করতে পারে বা বড় struct হয় সাধারণ উপাদান অ্যাক্সেস দ্বারা প্রভাবিত হতে একটি পয়েন্টার ব্যবহার struct T


4
আপনি ঠিক বলেছেন যে পয়েন্টার গাণিতিকের প্রকৃতি অপ্রাসঙ্গিক, তবে অ্যারের ঘোষিত আকারের বাইরে অ্যাক্সেস সম্পর্কে আপনি ভুল । দেখুন N1494 (সর্বশেষ প্রকাশ্য C1x খসড়া) অধ্যায় 6.5.6 অনুচ্ছেদ 8 - আপনি এমনকি করতে মঞ্জুরিপ্রাপ্ত নন উপরন্তু অতীতের একটির বেশি উপাদান অ্যারের ঘোষণা আকার একটি পয়েন্টার লাগে এবং আপনি এটি ডি-রেফারেন্স করতে পারেন না এমনকি যদি এটি অতীত মাত্র একটি উপাদান।
zwol

1
@ জ্যাক: যদি বস্তুটি অ্যারে হয় তবে এটি সত্য। এটি সত্য নয় যদি অবজেক্ট কোনও বরাদ্দকৃত বস্তু mallocযার দ্বারা অ্যারে হিসাবে অ্যাক্সেস করা হচ্ছে বা যদি এটির চেয়ে বড় স্ট্রাক্ট যা একটি পয়েন্টারের মাধ্যমে একটি ছোট স্ট্রাক্টে অ্যাক্সেস করা হচ্ছে যার উপাদানগুলি বৃহত্তর কাঠামোর উপাদানগুলির প্রাথমিক উপসেট, অন্যগুলির মধ্যে মামলা।
আর .. গীটহাব বন্ধ করুন ICE

6
+1 যদি mallocপয়েন্টার পাটিগণিত দিয়ে অ্যাক্সেস করা যায় এমন কোনও মেমরির সীমা বরাদ্দ না করে তবে এটি কী ব্যবহার করবে? যদি p->s[1]হয় সংজ্ঞায়িত যে পয়েন্টার এরিথমেটিক জন্য অন্বিত চিনি, তারপর এই উত্তর নিছক reasserts যেমন মান দ্বারা mallocদরকারী। কী আলোচনা করার বাকি আছে? :)
ড্যানিয়েল আরউইকার

3
আপনি তর্ক করতে পারেন যে এটি আপনার পছন্দমতো যথাযথভাবে সংজ্ঞায়িত করা হয়েছে তবে এটি যে বাস্তবে তা পরিবর্তন করে না। মানকটি অ্যারের সীমা ছাড়িয়ে অ্যাক্সেস সম্পর্কে খুব স্পষ্ট, এবং এই অ্যারের সীমাটি 1। এটা ঠিক যে হিসাবে সহজ।
অরবিতের হালকাত্বের রেস

3
@ আর .., আমি মনে করি, আপনার ধারনা যে সমান তুলনা করা দুই পয়েন্টারকে একই আচরণ করা উচিত এটি ভুল। শাখা প্রবেশ করানো int m[1]; int n[1]; if(m+1 == n) m[1] = 0;অনুমান করে বিবেচনা করুন if। এটি nপড়ার সাথে সাথে 6.5.6 পি 8 (শেষ বাক্য) অনুযায়ী এটি ইউবি (এবং আরম্ভের নিশ্চয়তা নয় )। সম্পর্কিত: পাদটীকা 109 সহ 6.5.9 পি 6 ((রেফারেন্সগুলি সি 11 এন 1570 এর জন্য রয়েছে)) [...]
মাফসো

7

হ্যাঁ, এটি প্রযুক্তিগতভাবে অপরিবর্তিত আচরণ।

দ্রষ্টব্য, "স্ট্রাক হ্যাক" প্রয়োগের জন্য কমপক্ষে তিনটি উপায় রয়েছে:

(1) আকার 0 (উত্তরাধিকারের কোডের সর্বাধিক "জনপ্রিয়" উপায়) সহ অনুসরণকারী অ্যারে ঘোষণা করা । এটি স্পষ্টতই ইউবি, যেহেতু শূন্য আকারের অ্যারে ডিক্লোরেশন সর্বদা সি-তে অবৈধ থাকে যদিও এটি সংকলন করেও ভাষা কোনও সীমাবদ্ধতা লঙ্ঘনকারী কোডের আচরণ সম্পর্কে কোনও গ্যারান্টি দেয় না।

(২) সর্বনিম্ন আইনী আকারের সাথে অ্যারে ঘোষণা করা - ১ (আপনার কেস)। p->s[0]এক্ষেত্রে পয়েন্টার গাণিতিকের জন্য পয়েন্টার নিতে এবং এটি ব্যবহারের যে কোনও প্রচেষ্টা অপরিবর্তিত p->s[1]আচরণ behavior উদাহরণস্বরূপ, একটি ডিবাগিং বাস্তবায়নকে এমবেডড রেঞ্জের তথ্য সহ একটি বিশেষ পয়েন্টার তৈরি করার অনুমতি দেওয়া হয়, যা আপনি যখনই বাইরে পয়েন্টার তৈরি করার চেষ্টা করবেন তখন আটকাবে p->s[1]

(3) উদাহরণস্বরূপ, 10000 এর মতো "খুব বড়" আকারের সাথে অ্যারে ঘোষণা করা । ধারণাটি হ'ল ঘোষিত আকারটি প্রকৃত অনুশীলনে আপনার যে কোনও প্রয়োজন হতে পারে তার চেয়ে বড় হতে পারে। অ্যারে অ্যাক্সেসের পরিধি সম্পর্কে এই পদ্ধতিটি ইউবি মুক্ত। যাইহোক, অনুশীলনে অবশ্যই অবশ্যই আমরা সর্বদা স্বল্প পরিমাণ মেমরি বরাদ্দ করব (যতটা সত্যই প্রয়োজন তেমন)। আমি এর বৈধতা সম্পর্কে নিশ্চিত নই, অর্থাত্ ঘোষিত আকারের চেয়ে অবজেক্টের জন্য কম মেমরি বরাদ্দ করা কতটা আইনী (আমি ধরে নিই না যে আমরা "অ-বরাদ্দকৃত" সদস্যদের অ্যাক্সেস করি না) তার থেকে আমি কতটা আইনী তা অবাক করি I


1
(2) এ, s[1]নির্ধারিত আচরণ নয়। এটি একইরূপে *(s+1), যা একইরূপে *((char *)p + offsetof(struct T, s) + 1), যা charবরাদ্দকৃত অবজেক্টে একটিতে বৈধ পয়েন্টার ।
আর .. গীটহাব বন্ধ করুন ICE

অন্যদিকে, আমি প্রায় নিশ্চিত (3) অপরিজ্ঞাত আচরণ। আপনি যখনই কোনও ঠিকানায় থাকা কোনও স্ট্রাক্টের উপর নির্ভর করে যে কোনও ক্রিয়াকলাপ সম্পাদন করেন তখনই সংকলকটি স্ট্রাকের কোনও অংশ থেকে পড়া মেশিন কোড তৈরি করতে মুক্ত is এটি অকেজো হতে পারে, বা কঠোর বরাদ্দ চেক করার জন্য এটি একটি সুরক্ষা বৈশিষ্ট্য হতে পারে, তবে কোনও বাস্তবায়ন এটি করতে না পারার কোনও কারণ নেই।
আর .. গীটহাব বন্ধ করুন ICE

আর: যদি অ্যারেটিকে একটি আকার হিসাবে ঘোষণা করা হয় (কেবল foo[]সিনট্যাকটিক চিনি নয় *foo) তবে পয়েন্টার গাণিতিকটি কীভাবে করা হয়েছিল তা নির্বিশেষে তার ঘোষিত আকারের ছোট অংশ এবং তার বরাদ্দ আকারটি ইউবি হয়।
zwol

1
@ জ্যাক, আপনি বেশ কয়েকটি বিষয়ে ভুল হয়ে গেছেন। foo[]স্ট্রাক্টের জন্য সিনট্যাকটিক চিনি নয় *foo; এটি একটি C99 নমনীয় অ্যারে সদস্য। বাকিগুলির জন্য, আমার উত্তর এবং অন্যান্য উত্তরের মন্তব্যগুলি দেখুন।
আর .. গীটহাব বন্ধ করুন ICE

6
সমস্যাটি হল এই যে কমিটির কিছু সদস্য নিদারুণভাবে হয় চান এই "হ্যাক" UB হতে কারণ তারা কিছু পরীর দেশ যেখানে একটি সি বাস্তবায়ন পয়েন্টার সীমা বলবত্ পারে কল্পনা। উন্নত বা খারাপের জন্য, তবে, এটি স্ট্যান্ডার্ডের অন্যান্য অংশগুলির সাথে দ্বন্দ্ব করবে - সমতার জন্য পয়েন্টারগুলির তুলনা করার ক্ষমতা (যদি পয়েন্টারে নিজেই সীমানাটি এনকোড করা হত) বা কোনও বস্তুটি একটি কাল্পনিক ওভারলেড unsigned char [sizeof object]অ্যারের মাধ্যমে অ্যাক্সেসযোগ্য হতে পারে এমন প্রয়োজনীয়তা । আমি আমার দাবির সাথে দাঁড়িয়ে আছি যে প্রি-সি 99 এর জন্য নমনীয় অ্যারে সদস্য "হ্যাক" এর সুস্পষ্ট সংজ্ঞা রয়েছে।
আর .. গীটহাব বন্ধ করুন ICE

3

মানটি বেশ স্পষ্ট যে আপনি কোনও অ্যারের শেষের পাশে জিনিসগুলি অ্যাক্সেস করতে পারবেন না। (এবং পয়েন্টারগুলির মধ্য দিয়ে যাওয়া কোনও উপকারে আসে না, কারণ আপনাকে অ্যারে শেষের পরে একের পর এক ইনক্রিমেন্ট পয়েন্টারও দিতে দেওয়া হয় না)।

এবং "অনুশীলনে কাজ করার" জন্য। আমি জিসিসি / জি ++ অপ্টিমাইজারটিকে এই অবৈধ সিটির সাথে দেখা করার সময় মানকটির এই অংশটি এভাবে ভুল কোড তৈরি করে দেখেছি using


আপনি কি একটি উদাহরণ দিতে পারেন?
তাল

1

যদি একটি সংকলক কিছু গ্রহণ করে

টাইপডেফ স্ট্রাক্ট
  int লেন;
  চর ডাট [];
};

আমি মনে করি এটি অত্যন্ত স্পষ্ট যে এটি অবশ্যই 'ডেটা'র দৈর্ঘ্যের বাইরে সাবস্ক্রিপ্ট গ্রহণের জন্য প্রস্তুত থাকতে হবে। অন্যদিকে, কেউ যদি এমন কিছু কোড করে:

টাইপডেফ স্ট্রাক্ট
  int যাই হোক না কেন;
  চর ডাট [1];
} এমওয়াই_স্ট্রাক্ট;

এবং তারপরে পরে কিছুটা কাঠামো-> ডাট [এক্স] অ্যাক্সেস করে; আমি মনে করি না যে সংকলকটি অ্যাড্রেস-গণনা কোড ব্যবহার করার কোনও বাধ্যবাধকতার অধীনে রয়েছে যা x এর বড় মানগুলির সাথে কাজ করবে। আমি মনে করি যদি কেউ সত্যই নিরাপদ থাকতে চায়, তবে সঠিক দৃষ্টান্তটি আরও ভালো হবে:

# নির্ধারণ LARGEST_DAT_SIZE 0xF000
টাইপডেফ স্ট্রাক্ট
  int যাই হোক না কেন;
  চর ডাট [LARGEST_DAT_SIZE];
} এমওয়াই_স্ট্রাক্ট;

এবং তারপরে (আকারের (মাইস্ট্রাক্ট) -LARGEST_DAT_SIZE + কাঙ্ক্ষিত_আরয়_ দৈর্ঘ্য) বাইটগুলি (মনে রাখবেন যে যদি পছন্দসই_আরআর_ দৈর্ঘ্য LARGEST_DAT_SIZE এর চেয়ে বড় হয় তবে ফলাফল অপরিজ্ঞাত হতে পারে)।

ঘটনাক্রমে, আমি মনে করি শূন্য দৈর্ঘ্যের অ্যারে নিষিদ্ধ করার সিদ্ধান্তটি দুর্ভাগ্যজনক ছিল (টার্বো সি এর মতো কিছু পুরানো উপভাষা এটি সমর্থন করে) যেহেতু শূন্য দৈর্ঘ্যের অ্যারেটি এমন একটি চিহ্ন হিসাবে বিবেচিত হতে পারে যে সংকলককে অবশ্যই কোড তৈরি করতে হবে যা বৃহত্তর সূচকগুলির সাথে কাজ করবে will ।

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