روزبه شریف‌نسب
خواندن ۲ دقیقه·۵ سال پیش

اندیس آرایه رو دست کاربر نده

یه موردی رو که اکثرا دیدم برنامه‌نویس‌های تازه‌کار رعایت نمی‌کنیم اینه که چک نمی‌کنیم ورودی‌ای که از کاربر گرفتیم و قراره به عنوان اندیس آرایه استفاده بشه، داخل آرایه هست یا نه. مثلا اگر به عنوان کاربر ورودی ۱۰۱ وارد کنم و اندازه آرایه ۱۰ تا باشه، مشخصه که ۱۰۱ خارچ از آرایه است و برنامه باید خطا بده ولی توی زبان‌های مختلف، این مورد خیلی خوب چک نمی‌شه، یا اگر هم چک بشه اکسپشن پرتاب می‌شه و باعث اختالال در برنامه می‌شه ولی چون ما از کاربر ورودی گرفتیم منطقی‌تر اینه که در صورتی که ورودی در بازه مورد نظر نبود مسالمت آمیز یه دیالوگ یا پنجره باز کنیم و بگیم که ورودی معتبر نبود و یه ورودی در بازه فلان وارد کن.

پس، هیچ وقت یه ورودی که از کاربر گرفتید (یا به هر دلیلی مطمین نیستید از بازه‌ش) رو مستقیم اندیس ارایه نکنید. فرض رو بر بد بودن ورودی بگذارید که اندیس‌ اشتباه وارد شده. چک کردنش هم ساده‌است و با یه if امکان‌پذیره، اگه ورودی بزرگ‌‌تر مساوی طول آرایه بود یا منفی بود یعنی بیرون آرایه هست و خطای وجود داره.

اما اگر این چک رو انجام ندیم (که تا حالا انجام نمی‌دادیم) چه خطری داره؟

توی جاوا اتفاقی که می‌افته اینه که خود جاوا موقع دسترسی به المنت‌های آرایه این bound check رو انجام می‌ده و اگر ورودی داخل محدوده ارایه نباشه exception پرت می‌شه و ما هم که عموما حواسمون به catch کردن این اکسپشن نیست، پس برنامه با خطا خارج می‌شه در حالی که چاپ کردن یه invalid input ساده هم می‌تونست کافی باشه.

توی زبان‌های دیگه چه اتفاقی می‌افته؟

هر زبانی ممکنه یه واکنش نشون بده مثلا زبان سی/سی‌پلاس‌پلاس این چک رو خودش انجام نمی‌ده و صرفا به یه خونه invalid توی حافظه می‌خواد دسترسی پیدا کنه (مثل حالت dangling pointer) که ممکنه OS برنامه رو متوقف کنه (segmentation fault) یا حتی بدتر، اون خونه جزو برنامه خودمون باشه ولی آدرس یه آرایه و متغیر دیگه باشه و اشتباهی توی اون تغییر بدیم و باگ‌های حیلی عجیب به وجود بیاد. چرا؟ چون یه if برای چک کردن bound نذاشتیم.

باز زبان‌های متفاوت ممکنه کار‌های عجیب‌تری هم بکنند مثلا پایتون با اندیس منفی، خونه ها رو از آخر می‌شماره (مثلا -۱ میشه آخری) حالا شما بیا دیباگ کن :)


خلاصه: هروقت ورودی از کاربر گرفتید مستقیم توی اندیس قرارش ندید و حتما حتما قبلش با یه if ساده چکش کنید.

همینجا بگم که روزبه شریف نسب درسته و نه شریف نصب یا شریفی نسب یا هرچیز غلط دیگه..
شاید از این پست‌ها خوشتان بیاید