جلوگیری از integer overflow
اکتبر 4, 2010 4 دیدگاه
هر نوع عددی در زبان C++ دارای محدوده خاصی است، بطور مثال برای نوع short int اعداد میتوانند در بازهای بین -32768 و 32767 ذخیره شوند، ولی اگر عددی از این بازه فراتر رفت؟ در اینحالت integer overflow رخ خواهد داد. بطور مثال:
short int x = 32767;
x = x + 1; //x = -32768
با توجه به این مثال، مقدار x حداکثر مقداری است که نوع short int میتواند ذخیره کند، اگر عدد ۱ را به این مقدار اضافه کنیم از بازه قابل قبول فراتر خواهد رفت و integer overflow رخ خواهد داد. در نتیجه مقدار x تغییر علامت داده و برابر منفی 32768 میگردد. برای جلوگیری از چنین تغییر علامتهای ناگهانی و برای جلوگیری از محاسبات غلط، باید از integer overflow جلوگیری نمود. روشهای متفاوتی برای جلوگیری از integer overflow میتواند مورد استفاده قرار گیرد.
از یک تابع یا کلاس کمکی استفاده کنید. تابعی ایجاد کنید تا قبل از محاسبات بررسی کند که آیا integer overflow صورت میگیرد یا خیر. بطور مثال تابع is_safe_add این کار را انجام میدهد:
short int x = 32767, y = 32767, z;
if(is_safe_add(x, y)) z = x + y;
تابع is_safe_add بررسی میکند که آیا نتیجهٔ جمع دو عدد x و y بدون integer overflow خواهد بود یا خیر. بنابراین در مثال قبل، هیچگاه عمل جمع صورت نخواهد گرفت زیرا این تابع، مقدار false را برخواهد گرداند. برای پیادهسازی تابع is_safe_add میتوانید از چند شرط ساده برای کنترل بازههای اعداد x و y استفاده کنید. به جای ایجاد تابعی به نام is_safe_add میتوانید یک کلاس جدید برای کار با نوع short int ایجاد کنید:
ShortInt x = 32767;
x = x + 1; //throw an exception
در این نمونه مثال، «عملگر +» در کلاس ShortInt سربارگذاری و پیادهسازی شده است تا در صورتیکه integer overflow رخ میدهد، یک استثناء برای توقف اجرای کدها، صادر گردد.
مقادیری که در متغیر ذخیره میشوند را محدود کنید. ورودیهای کاربر را محدود کنید، تا زمانیکه مقادیر بزرگی در متغیرها ذخیره نشوند، احتمال رخدادن integer overflow ممکن نیست. این روش یک مزیت نسبت به روش قبل دارد و آن این است که قبل از هر محاسبهای، نیاز به بررسی احتمال وقوع integer overflow نیست. بنابراین سرعت محاسبات در این روش بیشتر از روش قبل خواهد بود. با توجه به اینکه معمولاً کاربر با اعداد بزرگ سر و کار ندارد و عملاً این روش بر روی نیازهای کاربر تأثیر منفی نخواهد گذاشت. به عنوان یک نکته، تشخیص احتمال integer overflow ساده و قابل جلوگیری خواهد بود اگر هوشیار باشید و این احتمال را نادیده نگیرید. پس اگر محدودیتها بر روی کاربر اعمالشده و فقط اشتباه برنامهنویس ممکن است علت integer overflow باشد، برای کمک به برنامهنویس (خود شما) بررسی امکان وقوع integer overflow را در ماکروی assert قرار دهید، تا درصورتیکه برنامهنویس (خود شما) سهواً اشتباه کرد، در مرحله تست و اشکالزدایی به او کمک شود تا ایراد را راحتتر پیدا کند، برای انتشار نهایی برنامه با تعریف ماکروی NDEBUG همهٔ شرطهای درون ماکروی assert نادیده گرفته خواهند شد.
نادیدهگیری احتمال وقوع integer overflow میتواند صدمات امنیتی جدی را بر روی برنامههای مهم و بحرانی وارد کند، همانطور که شما دسترسی به اعضای آرایه را کنترل میکنید تا از محدودهٔ آرایهها فراتر نروید، محدوده انواع عددی را نیز نباید فراموش کنید تا از صحت درستی محاسبات انجامشده اطمینان حاصل کنید.
ویرایش: بهرحال قبل از هر چیز بهتر است ابتدا محاسبات را طوری تغییر دهید که integer overflow رخ ندهد، اگر ممکن نبود، آنوقت از روشهای قبل استفاده کنید. ویرایش: جناب آقای توکلی، مثال بسیار خوبی را برای این حالت در قسمت دیدگاهها نوشتهاند.
دانلود کتاب آموزش پارسیکس