যদি একটি সংখ্যা খুব বড় হয় তবে এটি কি পরবর্তী মেমরির অবস্থানটিতে ছড়িয়ে পড়ে?


30

আমি সি প্রোগ্রামিং পর্যালোচনা করে এসেছি এবং কেবল দু'টো জিনিস আমাকে বিরক্ত করছে।

উদাহরণস্বরূপ এই কোডটি নেওয়া যাক:

int myArray[5] = {1, 2, 2147483648, 4, 5};
int* ptr = myArray;
int i;
for(i=0; i<5; i++, ptr++)
    printf("\n Element %d holds %d at address %p", i, myArray[i], ptr);

আমি জানি যে কোনও int ইতিবাচক 2,147,483,647 এর সর্বোচ্চ মান ধরে রাখতে পারে। সুতরাং এটির ওপরে গিয়ে, এটি কি পরবর্তী মেমরি ঠিকানায় "ছড়িয়ে পড়ে" যার ফলে উপাদানটি সেই ঠিকানায় "-2147483648" হিসাবে উপস্থিত হয়? তবে তারপরেও এটি সত্যিকার অর্থে আসে না কারণ আউটপুটে এটি এখনও বলেছে যে পরবর্তী ঠিকানাটি 4, তারপরে 5 মান রাখে যদি সংখ্যাটি পরবর্তী ঠিকানায় ছড়িয়ে পড়ে তবে সেই ঠিকানায় সঞ্চিত মানটি পরিবর্তন হবে না? ?

আমি অস্পষ্টভাবে এমআইপিএস অ্যাসেমব্লিতে প্রোগ্রামিং এবং এড্রেসগুলি প্রোগ্রামের সময় ধাপে ধাপে এই ঠিকানাগুলিতে নির্ধারিত মানগুলি পরিবর্তিত হতে দেখি watching

যদি না আমি ভুলভাবে মনে রাখছি তবে এখানে আরও একটি প্রশ্ন রয়েছে: যদি কোনও নির্দিষ্ট ঠিকানায় নির্ধারিত সংখ্যাটি যদি প্রকারের চেয়ে বড় হয় (মাইআরাই [2] এর মতো) তবে এটি পরবর্তী ঠিকানায় সঞ্চিত মানগুলিকে প্রভাবিত করে না?

উদাহরণ: 0x10010000 ঠিকানায় আমাদের কাছে মাইনাম = 4 বিলিয়ন। অবশ্যই মাইনিম 4 বিলিয়ন সঞ্চয় করতে পারে না তাই এটি ঠিকানায় কিছু নেতিবাচক সংখ্যা হিসাবে উপস্থিত হয়। এই বিশাল সংখ্যক সঞ্চয় করতে সক্ষম না হওয়া সত্ত্বেও 0x10010004 এর পরবর্তী ঠিকানায় সঞ্চিত মানের উপর এর কোনও প্রভাব নেই। সঠিক?

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

আমি ওভারবোর্ডে গিয়ে থাকলে দুঃখিত। আমি এখান থেকে সারাদিন একটি বড় মস্তিষ্কের অভাব অনুভব করি।


10
আপনি স্ট্রিং ওভাররনগুলির সাথে বিভ্রান্ত হচ্ছেন
রবি ডি

19
হোমওয়ার্ক: পরিবর্তন একটি সহজ CPU- র যাতে এটি না বিষ্ফোরণের। আপনি দেখতে পাবেন যে যুক্তিটি আরও জটিল হয়ে উঠবে, এটি একটি "বৈশিষ্ট্য" এর জন্য যা প্রথম স্থানে কার্যকর না হয়ে সর্বত্র সুরক্ষার গর্তের গ্যারান্টি দেয়।
ফিহাগ

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

1
একটি সহজ পরীক্ষা লিখুন, আমি কোনও সি প্রোগ্রামার নই তবে এর লাইনে কিছু আছে int c = INT.MAXINT; c+=1;এবং দেখুন সি এর কি হয়েছে।
জোনএইচ

2
@ জোনএইচ: সমস্যাটি অনির্ধারিত আচরণের ওভারফ্লো flow এসি সংকলক সেই কোডটি স্পট করতে পারে এবং অনুমিত করতে পারে যে এটি অ্যাক্সেসযোগ্য কোড নয় কারণ এটি নিঃশর্তভাবে প্রবাহিত। অ্যাক্সেসযোগ্য কোড যেহেতু কোনও বিষয় নয় তাই এটি নির্মূল করা যেতে পারে। শেষ ফলাফল: কোনও কোড বাকি নেই।
এমসালটার

উত্তর:


48

না, তা হয় না। সি তে, ভেরিয়েবলগুলির সাথে কাজ করার জন্য মেমরি ঠিকানার একটি নির্দিষ্ট সেট থাকে। আপনি যদি 4-বাইট সহ কোনও সিস্টেমে কাজ করে থাকেন intsএবং আপনি একটি intভেরিয়েবল সেট করে থাকেন 2,147,483,647এবং তারপরে যোগ করুন1 তবে ভেরিয়েবলটি সাধারণত থাকে -2147483648। (বেশিরভাগ সিস্টেমে। আচরণটি প্রকৃতপক্ষে সংজ্ঞায়িত)) অন্য কোনও মেমরির অবস্থান পরিবর্তন করা হবে না।

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

কিছুটা দিকের দিকে তাকানো হয়েছে, টাইপটি যদি কেবলমাত্র 8 টি বিট সঞ্চয় করতে পারে এবং আপনি মানটি চাপিয়ে দেওয়ার চেষ্টা করেন 1010101010101কিছুটা দিকের যদি একটি কেস দিয়ে করেন তবে আপনি নীচের 8 টি বিট দিয়ে শেষ করতে পারেন, বা 01010101

আপনার উদাহরণে, আপনি যা করেন তা নির্বিশেষে myArray[2],myArray[3] '4' থাকতে হবে। কোনও "স্পিল ওভার" নেই। আপনি 4-বাইটের বেশি এমন কিছু রাখার চেষ্টা করছেন যা নীচের 4 টি বাইট ছেড়ে কেবল উচ্চ প্রান্তে সমস্ত কিছু বন্ধ করে দেবে। বেশিরভাগ সিস্টেমে এটির ফলাফল হবে -2147483648

ব্যবহারিক দৃষ্টিকোণ থেকে আপনি কেবল এটি নিশ্চিত করতে চান যে এটি কখনই ঘটে না। এই ধরণের ওভারফ্লোগুলি প্রায়শই হার্ড-টু-সলভ ত্রুটিগুলির ফলস্বরূপ। অন্য কথায়, আপনি যদি ভাবেন যে আপনার সমস্ত মূল্যবোধে কোনও সুযোগ রয়েছে তবে বিলিয়নে থাকবে, ব্যবহার করবেন না int


52
আপনি যদি 4-বাইট ইনট সহ কোনও সিস্টেমে কাজ করে থাকেন এবং আপনি কোনও int ভেরিয়েবল 2,147,483,647 এ সেট করেন এবং তারপরে 1 যোগ করেন, ভেরিয়েবলটি -2147483648 থাকবে। => না , এটি অনির্ধারিত আচরণ , সুতরাং এটি প্রায় লুপ বা এটি সম্পূর্ণ অন্য কিছু করতে পারে; আমি ওভারফ্লো অনুপস্থিতির উপর ভিত্তি করে চেকগুলি অপ্টিমাইজ করা সংকলকগুলি দেখেছি এবং উদাহরণস্বরূপ অসীম লুপ পেয়েছে ...
ম্যাথিউ এম।

দুঃখিত, হ্যাঁ, আপনি ঠিক বলেছেন। আমার সেখানে "সাধারণত" যুক্ত করা উচিত ছিল।
রোবট

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

@ হবস: সমস্যাটি হ'ল যখন সংকলকগণ অপরিজ্ঞাত আচরণের কারণে প্রোগ্রামটি ম্যাঙ্গেল করে, প্রকৃতপক্ষে প্রোগ্রামটি চালানো আসলেই একটি অপ্রত্যাশিত আচরণ তৈরি করে, যা মেমরির ওভার রাইটিংয়ের সাথে তুলনীয় হয়।
ম্যাথিউ এম।

24

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

তবে স্বাক্ষরযুক্ত স্বাক্ষর পূর্ণসংখ্যার ওভারফ্লো ভাল সংজ্ঞায়িত। এটি Modulo UINT_MAX + 1 মোড়ানো করবে। আপনার পরিবর্তনশীল দ্বারা দখল করা মেমরিটি প্রভাবিত হবে না।

এছাড়াও https://stackoverflow.com/q/18195715/951890 দেখুন


স্বাক্ষরিত পূর্ণসংখ্যার ওভারফ্লো ঠিক একইভাবে সংজ্ঞায়িত হিসাবে স্বাক্ষরযুক্ত পূর্ণসংখ্যা ওভারফ্লো হয়। শব্দটির যদি $ N $ বিট থাকে তবে স্বাক্ষরিত পূর্ণসংখ্যার ওভারফ্রোলের উপরের সীমানাটি $$ 2 ^ {N-1} -1 at এ থাকে (যেখানে এটি $ -2 ^ {N-1}} এর কাছাকাছি আবৃত হয়) যেখানে স্বাক্ষরবিহীন পূর্ণসংখ্যার ওভারফ্লোর জন্য উপরের সীমানাটি $$ 2 ^ N - 1 $$ (যেখানে এটি প্রায় $ 0 $ এর মধ্যে আবৃত হয়) at সংযোজন এবং বিয়োগের জন্য একই পদ্ধতি, সংখ্যার পরিসরের একই আকার ($ 2 ^ N $) যা প্রতিনিধিত্ব করা যায়। ওভারফ্লো মাত্র একটি পৃথক সীমানা।
রবার্ট ব্রিস্টো-জনসন 22'16

1
@ রবার্টব্রিস্টো-জনসন: সি স্ট্যান্ডার্ড অনুযায়ী নয়।
ভন ক্যাটো

ভাল, মান কখনও কখনও anachronistic হয়। এসও রেফারেন্সের দিকে তাকালে একটি মন্তব্য রয়েছে যা এটিকে সরাসরি আঘাত করে: "যদিও এখানে গুরুত্বপূর্ণ নোটটি 2 এর পরিপূরক স্বাক্ষরিত গাণিতিক ব্যতীত অন্য কোনও কিছু ব্যবহার করে আধুনিক বিশ্বে কোনও আর্কিটেকচার থেকে যায় না That যে ভাষার মানগুলি এখনও বাস্তবায়নের অনুমতি দেয় উদাহরণস্বরূপ, পিডিপি -১ একটি খাঁটি historical
তিহাসিক

আমি এটা অনুমান করা নয় সি মান মধ্যে, কিন্তু আমি একটি বাস্তবায়ন যেখানে নিয়মিত বাইনারি গাণিতিক জন্য ব্যবহার করা হয় না হতে পারে অনুমান করা int। আমি মনে করি তারা ব্যবহার করতে পারে s'pose গ্রে কোড বা ছাত্রদলের বা EBCDIC । ধূমপান কেন কেউ গ্রে কোড বা ইবিসিডিকের সাথে পাটিগণিত করার জন্য হার্ডওয়্যার ডিজাইন করবে তবে তারপরে আবারও, কেন কেউ unsignedবাইনারি নিয়ে int2 এর পরিপূরক ব্যতীত অন্য কোনও কিছুতে স্বাক্ষর করতে পারে তা আমি জানি না ।
রবার্ট ব্রিস্টো-জনসন

14

সুতরাং, এখানে দুটি জিনিস রয়েছে:

  • ভাষা স্তর: সি এর শব্দার্থবিজ্ঞান কি কি
  • যন্ত্র স্তর: আপনি যে সমাবেশ / সিপিইউ ব্যবহার করেন সেগুলির শব্দার্থক শব্দগুলি

ভাষা স্তরে:

সি তে:

  • ওভারফ্লো এবং আন্ডারফ্লো স্বাক্ষরবিহীন জন্য মডুলো গাণিতিক হিসাবে সংজ্ঞায়িত করা হয় পূর্ণসংখ্যার হয়, সুতরাং তাদের মান "লুপস"
  • ওভারফ্লো এবং আন্ডারফ্লো স্বাক্ষরিত পূর্ণসংখ্যাগুলির জন্য অপরিজ্ঞাত আচরণ , সুতরাং যা কিছু ঘটতে পারে

তাদের জন্য একটি "কি কি" উদাহরণ চাইবে, আমি দেখেছি:

for (int i = 0; i >= 0; i++) {
    ...
}

মধ্যে পরিণত:

for (int i = 0; true; i++) {
    ...
}

এবং হ্যাঁ, এটি একটি বৈধ রূপান্তর।

এর অর্থ হ'ল কিছু অদ্ভুত সংকলক রূপান্তরের কারণে ওভারফ্লোতে মেমরির ওভাররাইট করার প্রকৃত সম্ভাবনা রয়েছে।

দ্রষ্টব্য: অনির্ধারিত আচরণ স্যানিটাইজারকে-fsanitize=undefined সক্রিয় করতে ডিবাগে কলং বা জিসিসি ব্যবহার যা স্বাক্ষরিত পূর্ণসংখ্যার আন্ডারফ্লো / ওভারফ্লোকে বাতিল করবে।

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

দ্রষ্টব্য: অ্যাড্রেস স্যানিটাইজারটি-fsanitize=address সক্রিয় করতে ডিবাগে কলং বা জিসিসি ব্যবহার করুন যা সীমানা অ্যাক্সেস বাতিল করবে।


যন্ত্র স্তরে :

এটি সত্যিই আপনার যে সমাবেশগুলির নির্দেশাবলী এবং সিপিইউ ব্যবহার করে তার উপর নির্ভর করে:

  • x86 এ, এডি ওভারফ্লো / আন্ডারফ্লোতে 2-পরিপূরক ব্যবহার করবে এবং অফ (ওভারফ্লো পতাকা) সেট করবে
  • ভবিষ্যতে মিল সিপিইউতে 4 টি পৃথক ওভারফ্লো মোড থাকবে Add :
    • মডুলো: 2-পরিপূরক মডুলো
    • ফাঁদ: একটি ফাঁদ তৈরি করা হয়, গণনা বন্ধ করে দেওয়া হচ্ছে
    • স্যাচুরেট: মান নিম্নতম প্রবাহে মিনিট বা ওভারফ্লোতে সর্বাধিক আটকে যায়
    • ডাবল প্রস্থ: ফলাফল একটি ডাবল প্রস্থ রেজিস্টারে উত্পন্ন হয়

নোট করুন যে জিনিসগুলি রেজিস্টারগুলিতে বা মেমোরিতে ঘটে কিনা, উভয় ক্ষেত্রেই সিপিইউ ওভারফ্লোতে মেমরির ওভাররাইট করে না।


শেষ তিনটি পদ্ধতিতে কী স্বাক্ষরিত হয়েছে? (নেই প্রথম এক জন্য কোন ব্যাপার না, যেমন এটি 2-সম্পূরক আছে।)
Deduplicator

1
@ ডিডুকিপেটর: মিল সিপিইউ প্রোগ্রামিং মডেলের পরিচিতি অনুসারে স্বাক্ষরিত সংযোজন এবং স্বাক্ষরবিহীন সংযোজনের জন্য বিভিন্ন অপকড রয়েছে; আমি আশা করি যে উভয় অপকডগুলি 4 টি মোডগুলিকে সমর্থন করবে (এবং বিভিন্ন বিট-প্রস্থ এবং স্কেলার / ভেক্টরগুলিতে অপারেট করতে সক্ষম হবে)। তারপরে আবার এটি এখনকার বাষ্পের হার্ডওয়্যার;)
ম্যাথিউ এম।

4

স্টিভেনবার্নাপের উত্তরটি আরও জানাতে, কম্পিউটারগুলি কীভাবে মেশিন-স্তরে কাজ করে তা হ'ল এটি হওয়ার কারণ।

আপনার অ্যারে মেমরিতে সঞ্চয় করা হয় (যেমন র‌্যামে)। যখন একটি গাণিতিক অপারেশন করা হয়, তখন মেমরির মানটি সার্কিটের ইনপুট রেজিস্টারে অনুলিপি করা হয় যা পাটিগণিত (ALU: পাটিগণিত লজিক ইউনিট ) সম্পাদন করে, ফলস্বরূপ ফলাফলটি তৈরি করে ইনপুট রেজিস্টারে থাকা ডেটাগুলিতে অপারেশন করা হয় is আউটপুট রেজিস্টারে। এই ফলশ্রুতিটি মেমরির সঠিক ঠিকানায় মেমরিতে ফিরে অনুলিপি করা হয়, মেমরির অন্যান্য ক্ষেত্রগুলিকে বাছাই করা।


4

প্রথম (সি 99 মান ধরে), আপনি <stdint.h>স্ট্যান্ডার্ড শিরোনাম অন্তর্ভুক্ত করতে পারেন এবং সেখানে সংজ্ঞায়িত কিছু প্রকারের ব্যবহার করতে পারেন , উল্লেখযোগ্যভাবে int32_tএটি হ'ল 32 বিট স্বাক্ষরিত পূর্ণসংখ্যা, বা uint64_tযা হ'ল 64 বিট স্বাক্ষরবিহীন পূর্ণসংখ্যার, ইত্যাদি। int_fast16_tপারফরম্যান্স কারণে আপনি ধরণের ব্যবহার করতে পারেন ।

স্বাক্ষরযুক্ত পাটিগণিত সংলগ্ন মেমরি অবস্থানগুলিতে কখনও ছড়িয়ে দেয় না (বা ওভারফ্লো) কখনও ব্যাখ্যা করে এমন উত্তরগুলি পড়ুন others স্বাক্ষরিত ওভারফ্লোতে অপরিজ্ঞাত আচরণ থেকে সাবধান থাকুন ।

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

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