সি ++ এবং অপরিজ্ঞাত আচরণে (ইউবি) স্বাক্ষরিত ওভারফ্লো


56

আমি নীচের মত কোড ব্যবহার সম্পর্কে ভাবছি

int result = 0;
int factor = 1;
for (...) {
    result = ...
    factor *= 10;
}
return result;

যদি লুপটি nবারবার পুনরাবৃত্তি হয় তবে ঠিক সময়ের সাথে factorগুণিত হয় । তবে, সর্বদা মোট বার দ্বারা গুণিত হওয়ার পরে ব্যবহৃত হয় । যদি আমরা ধরে নিই যে লুপের শেষ পুনরাবৃত্তিকে বাদ দিয়ে কখনই ওভারফ্লো হয় না তবে লুপের শেষ পুনরাবৃত্তির উপর দিয়ে প্রবাহিত হতে পারে তবে এই জাতীয় কোডটি গ্রহণযোগ্য হবে কি? এই ক্ষেত্রে, ওভারফ্লো হওয়ার পরে এর মান সম্ভবত ব্যবহার করা হবে না।10nfactor10n-1factorfactor

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

প্রশ্নে আসল কোডটি একটি দৃ tight় অভ্যন্তরীণ লুপে ব্যবহৃত হয় যা মোট সিপিইউ সময়ের একটি বড় অংশকে রিয়েল-টাইম গ্রাফিক্স অ্যাপ্লিকেশনে গ্রহণ করে।


5
আমি এই প্রশ্নটিকে অফ-টপিক হিসাবে বন্ধ করতে ভোট দিচ্ছি কারণ এই প্রশ্নটি এখানে কোডেরভিউ.স্ট্যাকেক্সচেঞ্জ.কম এ হওয়া উচিত ।
কেভিন অ্যান্ডারসন

31
@ কেভিন অ্যান্ডারসন, এখানে এটি বৈধ নয়, উদাহরণ কোডটি ঠিক করতে হবে, কেবল উন্নত হয়নি।
বাথশেবা

1
পছন্দ করুন
লাইটনেস রেস

1
@ লাইটনেসেসেসিথমোনিকা: স্ট্যান্ডার্ডের লেখকরা আশা করেছিলেন এবং আশা করেছিলেন যে বিভিন্ন প্ল্যাটফর্ম এবং উদ্দেশ্যগুলির জন্য বাস্তবায়িতকরণগুলি প্রোগ্রামারদের জন্য উপলব্ধ শব্দার্থকগুলি অর্থাত্‍ সেই প্ল্যাটফর্মগুলি এবং উদ্দেশ্যে কার্যকরভাবে বিভিন্ন পদ্ধতিতে প্রক্রিয়া করার মাধ্যমে স্ট্যান্ডার্ডকে এটি করার প্রয়োজন কিনা, এবং আরও জানিয়েছে যে তারা নন-পোর্টেবল কোডটি মান্য করতে চায় না। সুতরাং, প্রশ্নগুলির মধ্যে সাম্যতা নির্ভর করে যা বাস্তবায়নকে সমর্থন করা প্রয়োজন তার উপর।
সুপারক্যাট

2
@ সুপের্যাট বাস্তবায়ন-সংজ্ঞায়িত আচরণগুলির জন্য নিশ্চিত, এবং যদি আপনি জানেন যে আপনার সরঞ্জামচঞ্চের কিছু এক্সটেনশন রয়েছে আপনি ব্যবহার করতে পারেন (এবং আপনি বহনযোগ্যতার কোনও যত্ন নেই), জরিমানা। ইউবির জন্য? সন্দিহান।
হালকাতা রেস 23'

উত্তর:


51

সংকলকরা ধরে নেন যে কোনও বৈধ সি ++ প্রোগ্রামে ইউবি থাকে না। উদাহরণস্বরূপ বিবেচনা করুন:

if (x == nullptr) {
    *x = 3;
} else {
    *x = 5;
}

x == nullptrতারপরে যদি এটিকে নির্ধারণ করা হয় এবং একটি মান নির্ধারণ করা হয় তবে ইউবি। সুতরাং কোনও বৈধ প্রোগ্রামে এটি শেষ হওয়ার একমাত্র উপায় হ'ল কখন কখন x == nullptrসত্য ফল পাওয়া যায় না এবং সংকলকটি নিয়মের অধীনে ধরে নিতে পারে, উপরেরটি সমান:

*x = 5;

এখন আপনার কোডে

int result = 0;
int factor = 1;
for (...) {      // Loop until factor overflows but not more
   result = ...
   factor *= 10;
}
return result;

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

// nothing :(

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

1
এবং এটি এমনকি একটি "দরকারী অপ্টিমাইজেশন" হতে পারে যদি ফাংশনটি কেবলমাত্র লক্ষ্যগুলির উপরে বলা হয় INT_MAX >= 10000000000, যেখানে INT_MAXছোট যেখানে অন্যরকম ফাংশন বলা হয় ।
আর .. গিটহাব বন্ধ করুন ICE

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

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

2
@ গিলস- ফিলিপেইলé : প্রতিটি সি প্রোগ্রামারকে এলএলভিএম ব্লগ থেকে অনির্ধারিত আচরণ সম্পর্কে যা জানা উচিত তাও ভাল। এটি ব্যাখ্যা করে যে উদাহরণস্বরূপ স্বাক্ষরিত-পূর্ণসংখ্যার ওভারফ্লো ইউবি কম্পাইলারগুলি প্রমাণ করতে দেয় যে i <= nলুপগুলি সর্বদা i<nলুপের মতো অসীম are এবং int iপ্রথম 4 জি অ্যারের উপাদানগুলির সাথে সম্ভাব্য মোড়কের অ্যারে সূচককে পুনরায় চিহ্ন তৈরি করার পরিবর্তে একটি লুপের পয়েন্টার প্রস্থকে প্রচার করুন ।
পিটার কর্ডস

34

intওভারফ্লো এর আচরণ নির্ধারিত।

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

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

আপনি একটি ব্যবহার করা যাবে না unsignedজন্য টাইপ factorযদিও তারপর আপনি এর অবাঞ্ছিত রূপান্তর সম্পর্কে চিন্তা করতে হবে না intকরতে unsignedউভয় ধারণকারী এক্সপ্রেশন মধ্যে?


12
@nicomp; কেন না?
বৎশেবা

12
@ গিলস-ফিলিপেইলé: আমার উত্তর কি আপনাকে বলে না যে এটি সমস্যাযুক্ত? আমার প্রারম্ভিক বাক্যটি ওপি-র জন্য অগত্যা নেই, তবে বিস্তৃত সম্প্রদায় এবং factorঅ্যাসাইনমেন্টে "ব্যবহৃত" হয়েছে নিজের কাছে।
বাথশেবা

8
@ গিলস-
ফিলিপেইলé

1
@ বাথশেবা আপনি ঠিক বলেছেন, আমি আপনার উত্তর ভুল বুঝেছি।
গিলস-ফিলিপ পায়েল

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

23

বাস্তব-বিশ্বের অপ্টিমাইজার বিবেচনা করা অন্তর্দৃষ্টিযুক্ত হতে পারে ful লুপ আনরোলিং একটি পরিচিত কৌশল। মৌলিক ধারণা অপ লুপ আন্রোলিং হয়

for (int i = 0; i != 3; ++i)
    foo()

পর্দার পিছনে আরও কার্যকর করা হতে পারে

 foo()
 foo()
 foo()

এটি একটি নির্দিষ্ট বাউন্ড সহ সহজ কেস। তবে আধুনিক সংকলকগণ পরিবর্তনশীল সীমাগুলির জন্য এটিও করতে পারেন:

for (int i = 0; i != N; ++i)
   foo();

হয়ে

__RELATIVE_JUMP(3-N)
foo();
foo();
foo();

স্পষ্টতই এটি কেবল তখনই কাজ করে যদি সংকলক জানে যে এন <= 3। এবং এটিই আমরা মূল প্রশ্নে ফিরে যাই। কারণ সংকলক জানেন যে স্বাক্ষরিত ওভারফ্লো ঘটে না , এটি জানে যে 32 বিট আর্কিটেকচারে লুপটি সর্বোচ্চ 9 বার কার্যকর করতে পারে। 10^10 > 2^32। এটি 9 টি পুনরাবৃত্তি লুপ আনরোল করতে পারে। তবে উদ্দেশ্যটি ছিল সর্বোচ্চ 10 টি পুনরাবৃত্তি!

যা ঘটতে পারে তা হ'ল আপনি এন = 10 এর সাথে একটি সংসদীয় নির্দেশে (9-এন) আপেক্ষিক লাফ পান, সুতরাং -1 এর অফসেট যা নিজেই লাফের নির্দেশ। উফ। এটি সু-সংজ্ঞায়িত সি ++ এর জন্য একদম বৈধ লুপ অপ্টিমাইজেশন, তবে প্রদত্ত উদাহরণটি একটি শক্ত অনন্ত লুপে পরিণত হয়।


9

যে কোনও স্বাক্ষরিত পূর্ণসংখ্যার ওভারফ্লো অপরিশোধিত আচরণের ফলাফল দেয়, নির্বিশেষে ওভারফ্লোড মান হয় বা না পঠিত।

হতে পারে আপনার ব্যবহারের ক্ষেত্রে আপনি প্রথমে পুনরাবৃত্তিটি লুপের বাইরে তুলতে পারেন, এটি ঘুরিয়ে

int result = 0;
int factor = 1;
for (int n = 0; n < 10; ++n) {
    result += n + factor;
    factor *= 10;
}
// factor "is" 10^10 > INT_MAX, UB

এই মধ্যে

int factor = 1;
int result = 0 + factor; // first iteration
for (int n = 1; n < 10; ++n) {
    factor *= 10;
    result += n + factor;
}
// factor is 10^9 < INT_MAX

অপ্টিমাইজেশন সক্ষম করার সাথে, সংকলকটি উপরের দ্বিতীয় লুপটিকে একটি শর্তযুক্ত জাম্পে আনরোল করতে পারে।


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

সুষ্ঠু পর্যবেক্ষণ, আমি আমার উত্তর সংশোধন করেছি।
এলব্রুনোভস্কি

বা আরও সহজভাবে, শেষ পুনরাবৃত্তির খোসা factor *= 10;
পিটার

9

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

সংকলকগণ কার্যকর করার পথে সংকলনের সময় "সমস্যার কারণ" তৈরি করতে পারে যা তারা দেখতে পাবে সংকলন-দৃশ্যমান ইউবি, উদাহরণস্বরূপ ধরে নিন যে এই প্রাথমিক ব্লকগুলি কখনই পৌঁছায় নি।

প্রতিটি সি প্রোগ্রামারকে অপরিজ্ঞাত আচরণ সম্পর্কে কী জানা উচিত তাও দেখুন (এলএলভিএম ব্লগ)। সেখানে বর্ণিত হিসাবে, স্বাক্ষরিত-ওভারফ্লো ইউবি সংকলকগুলি প্রমাণ করতে দেয় যে for(... i <= n ...)লুপগুলি অসীম লুপ নয় এমনকি অজানা জন্য n। এটি তাদের পুনরায় সাইন-এক্সটেনশান পরিবর্তে ইন্ট লুপ কাউন্টারগুলিকে পয়েন্টার প্রস্থে "প্রচার" করতে দেয়। (সুতরাং সেই ক্ষেত্রে ইউবির পরিণতি কোনও অ্যারের কম 64k বা 4G উপাদানগুলির বাইরে অ্যাক্সেস করতে পারে, যদি আপনি iএর মান সীমাতে স্বাক্ষরিত মোড়কের প্রত্যাশা করছিলেন ))

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


সম্ভবত সবচেয়ে কার্যকর সমাধানটি হ'ল ম্যানুয়ালি শেষ পুনরাবৃত্তির খোসা ছড়িয়ে দেওয়া যাতে বিনা শর্ত factor*=10এড়ানো যায়।

int result = 0;
int factor = 1;
for (... i < n-1) {   // stop 1 iteration early
    result = ...
    factor *= 10;
}
 result = ...      // another copy of the loop body, using the last factor
 //   factor *= 10;    // and optimize away this dead operation.
return result;

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

এমনকি আপনি যদি স্বাক্ষরযুক্ত-> স্বাক্ষরযুক্ত রূপান্তরটি কখনই উপচে না পড়ে তবে স্বাক্ষরযুক্ত ধরণের সাথে এটি ব্যবহার করেও ঠিক fine

স্বাক্ষরবিহীন এবং 2 এর পরিপূরক স্বাক্ষরের মধ্যে রূপান্তর বিনামূল্যে (সমস্ত মানের জন্য একই বিট-প্যাটার্ন); সি ++ স্ট্যান্ডার্ড দ্বারা নির্দিষ্ট -> স্বাক্ষরযুক্ত স্বাক্ষরের জন্য মডুলো মোড়ানো কেবলমাত্র একই বিট-প্যাটার্নটি ব্যবহার করে তার পরিপূরক বা চিহ্ন / মাত্রার চেয়ে আলাদা l

এবং স্বাক্ষরযুক্ত-> স্বাক্ষরযুক্ত একইভাবে তুচ্ছ, যদিও এটি এর চেয়ে বড় মানের জন্য বাস্তবায়ন-সংজ্ঞায়িত INT_MAX। আপনি যদি সর্বশেষ পুনরুক্তি থেকে বিশাল স্বাক্ষরবিহীন ফলাফলটি ব্যবহার না করে থাকেন তবে আপনার উদ্বেগ করার কিছুই নেই। তবে আপনি যদি হন, স্বাক্ষরিত থেকে স্বাক্ষরিত থেকে রূপান্তরটি কি সংজ্ঞায়িত হয়? । মানটির সাথে মানানসই কেসটি বাস্তবায়ন-সংজ্ঞায়িত , যার অর্থ একটি বাস্তবায়ন অবশ্যই কিছু আচরণ বেছে নিতে পারে; বুদ্ধিমান ব্যক্তিরা কেবল স্বাক্ষরযুক্ত বিট প্যাটার্নটি কাটা (যদি প্রয়োজন হয়) কে স্বাক্ষরিত হিসাবে ব্যবহার করুন, কারণ এটি কোনও অতিরিক্ত কাজ ছাড়াই সীমান্তের মানগুলির জন্য একইভাবে কাজ করে। এবং এটি অবশ্যই ইউবি নয়। এত বড় স্বাক্ষরযুক্ত মানগুলি নেতিবাচক স্বাক্ষরিত পূর্ণসংখ্যায় পরিণত হতে পারে। যেমন জিসিসি এবং কলঙ্ক পরে int x = u; অপ্টিমাইজ করবেন নাx>=0সর্বদা সত্য হিসাবে, এমনকি ছাড়াই -fwrapv, কারণ তারা আচরণটি সংজ্ঞায়িত করে।


2
আমি এখানে ডাউনভোট বুঝতে পারি না। আমি বেশিরভাগ সর্বশেষ পুনরাবৃত্তি ছুলা সম্পর্কে পোস্ট করতে চেয়েছিলেন। তবে এখনও প্রশ্নের উত্তর দেওয়ার জন্য, ইউবি কীভাবে ছিঁড়ে ফেলা যায় সে সম্পর্কে আমি কয়েকটি পয়েন্ট একসাথে ছুঁড়েছি। আরও তথ্যের জন্য অন্যান্য উত্তর দেখুন।
পিটার

5

আপনি যদি লুপটিতে কয়েকটি অতিরিক্ত সমাবেশ নির্দেশাবলী সহ্য করতে পারেন তবে

int factor = 1;
for (int j = 0; j < n; ++j) {
    ...
    factor *= 10;
}

তুমি লিখতে পারো:

int factor = 0;
for (...) {
    factor = 10 * factor + !factor;
    ...
}

শেষ গুণটি এড়ানোর জন্য। !factorএকটি শাখা প্রবর্তন করবে না:

    xor     ebx, ebx
L1:                       
    xor     eax, eax              
    test    ebx, ebx              
    lea     edx, [rbx+rbx*4]      
    sete    al    
    add     ebp, 1                
    lea     ebx, [rax+rdx*2]      
    mov     edi, ebx              
    call    consume(int)          
    cmp     r12d, ebp             
    jne     .L1                   

এই কোড

int factor = 0;
for (...) {
    factor = factor ? 10 * factor : 1;
    ...
}

অপ্টিমাইজেশনের পরে শাখাবিহীন সমাবেশেও ফলাফল:

    mov     ebx, 1
    jmp     .L1                   
.L2:                               
    lea     ebx, [rbx+rbx*4]       
    add     ebx, ebx
.L1:
    mov     edi, ebx
    add     ebp, 1
    call    consume(int)
    cmp     r12d, ebp
    jne     .L2

(জিসিসি 8.3.0 দিয়ে সংকলিত -O3)


1
লুপের বডিটি বড় না হলে কেবল সর্বশেষ পুনরাবৃত্তির খোসা ছাড়াই সহজ। এটি একটি চালাক হ্যাক তবে factorকিছুটা লুপ বহনকারী নির্ভরতা শৃঙ্খলার বিলম্বকে বাড়িয়ে তোলে । বা না থাক: যখন এটি 2x কর্মদিবসের করার প্রনয়ন এটা শুধু কর্মদিবসের + যোগ যেমন দক্ষ করতে যেমন সম্বন্ধে f *= 10যেমন f*5*2, সঙ্গে testপ্রথম দ্বারা লুকানো লেটেন্সি LEA। তবে এটি লুপের ভিতরে অতিরিক্ত উফস ব্যয় করে তাই একটি সম্ভাব্য থ্রুপুট ডাউনসাইড (বা কমপক্ষে একটি হাইপারথ্রেডিং-বন্ধুত্বের সমস্যা) আছে
পিটার

4

আপনি forবিবৃতিটির প্রথম বন্ধনীতে কী দেখান নি তবে আমি ধরে নেব এটি এরকম কিছু:

for (int n = 0; n < 10; ++n) {
    result = ...
    factor *= 10;
}

আপনি কেবল কাউন্টার ইনক্রিমেন্ট এবং লুপ সমাপ্তির চেকটি শরীরে সরাতে পারেন:

for (int n = 0; ; ) {
    result = ...
    if (++n >= 10) break;
    factor *= 10;
}

লুপে সমাবেশের নির্দেশাবলীর সংখ্যা একই থাকবে।

আন্দ্রে আলেকজান্দ্রেস্কুর উপস্থাপনা দ্বারা অনুপ্রাণিত "মানুষের মন মধ্যে গতি পাওয়া যায়"।


2

ফাংশনটি বিবেচনা করুন:

unsigned mul_mod_65536(unsigned short a, unsigned short b)
{
  return (a*b) & 0xFFFFu;
}

প্রকাশিত নীতি অনুযায়ী, স্ট্যান্ডার্ড লেখক প্রত্যাশিত হতো যে যদি এই ফাংশন (যেমন) 0xc000 এবং 0xc000 অফ আর্গুমেন্ট সঙ্গে একটি প্রচলিত 32 বিট কম্পিউটার, উপর প্রার্থনা হয়েছিল operands প্রচার *করতে signed intগণনার -0x10000000 উত্পাদ কারণ হবে যখন রূপান্তরিত যা unsignedউত্পাদ হবে 0x90000000u--দী একই উত্তর যেন তারা করেছিল unsigned shortহিসাবে পদোন্নতি unsigned। তবুও, জিসিসি কখনও কখনও ওভারফ্লো দেখা দিলে সেই ফাংশনটিকে এমনভাবে অনুকূল করে তোলে যেগুলি অযৌক্তিকভাবে আচরণ করবে। কোনও কোড যেখানে ইনপুটগুলির সংমিশ্রণে কোনও ওভারফ্লো হতে পারে সেই -fwrapvবিকল্পের সাথে অবশ্যই প্রক্রিয়া করা উচিত যদি না ইচ্ছাকৃতভাবে-ত্রুটিযুক্ত ইনপুটটির স্রষ্টাদের তাদের পছন্দমতো স্বেচ্ছাসেবক কোড কার্যকর করার অনুমতি না দেওয়া হয়।


1

কেন এটি না:

int result = 0;
int factor = 10;
for (...) {
    factor *= 10;
    result = ...
}
return result;

এটি ...লুপ বডিটি চালায় না factor = 1বা factor = 10কেবল 100 এবং তার চেয়ে বেশি উচ্চতর। আপনাকে প্রথম পুনরাবৃত্তিটি খোলা করতে হবে এবংfactor = 1 আপনি যদি এটি কাজ করতে চান তবে এখনও শুরু করবেন ।
পিটার কর্ডেস

1

অপরিজ্ঞাত আচরণের বিভিন্ন মুখ রয়েছে এবং গ্রহণযোগ্য যা ব্যবহারের উপর নির্ভর করে।

টাইট ইনার-লুপ যা রিয়েল-টাইম গ্রাফিক্স অ্যাপ্লিকেশনে মোট সিপিইউ সময়ের একটি বড় অংশ গ্রহণ করে

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

প্রথমত, মান আছে। এই দৃষ্টিকোণ থেকে, আলোচনা করার মতো কিছুই নেই এবং ন্যায়সঙ্গত হওয়ার কোনও উপায় নেই, আপনার কোডটি কেবল অবৈধ। কোনও ifs বা কখন নেই, এটি কেবল একটি বৈধ কোড নয়। আপনি পাশাপাশি বলতে পারেন যে এটি আপনার দৃষ্টিকোণ থেকে মাঝারি আঙুলের আপ, এবং 95-99% সময় আপনি যেভাবেই যেতে ভাল হবেন।

এর পরে, হার্ডওয়্যার পাশ রয়েছে। কিছু অস্বাভাবিক, অদ্ভুত স্থাপত্য রয়েছে যেখানে এটি একটি সমস্যা। আমি "অসাধারণ, অদ্ভুত" বলছি কারণ সমস্ত কম্পিউটারের ৮০% (বা দুটি আর্কিটেকচার যা একসাথে সমস্ত কম্পিউটারের 95%) তৈরি করে, সেই এক আর্কিটেকচারে "ওহ, যাই হোক না কেন, যত্ন নেই" হার্ডওয়্যার স্তরের জিনিস। আপনি অবশ্যই একটি আবর্জনা পান (যদিও এখনও অনুমানযোগ্য) ফলাফল পান তবে কোনও খারাপ জিনিস ঘটে না। তা নয়
প্রতিটি আর্কিটেকচারের ক্ষেত্রে, আপনি খুব ভালভাবে ওভারফ্লোতে একটি ফাঁদ পেতে পারেন (যদিও আপনি গ্রাফিক্স অ্যাপ্লিকেশন সম্পর্কে কীভাবে কথা বলছেন তা দেখে, যেমন একটি বিজোড় আর্কিটেকচারে থাকার সম্ভাবনা বরং ছোট)। বহনযোগ্যতা একটি সমস্যা? যদি তা হয় তবে আপনি বিরত থাকতে চাইতে পারেন।

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

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

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