خطر اندیس متغیر در آرایه‌‌ | زبان برنامه نویسی C

 از موارد بسیار کاربردی در برنامه‌نویسی با زبان C، آرایه‌ها هستند. در اینجا می‌خواهیم به نکته‌ای در خصوص آرایه‌ها اشاره کنیم که عدم توجه به آن، می‌تواند موجب باگ‌های خطرناک در برنامه شود.

در زبان C دست ما برای انجام بسیاری از کارها باز است. اگرچه این ویژگی می‌تواند به ما قدرت زیادی ببخشد، اما در عین حال می‌تواند باعث شود برنامه‌ای بنویسیم که پر از باگ است. آن هم باگ‌هایی که پیدا کردنشان بسیار سخت و زمان‌بر است. به همین دلیل شرکت‌ها و برنامه نویسان حرفه‌ای برای آنکه در دام این مشکلات نیفتند، قواعدی برای خود وضع می‌کنند که تا حد زیادی مانع از به وجود آمدن چنین مشکلاتی می‌شود.

در برنامه‌ای لازم بود تا اطلاعات رسیده به پورت UART1 میکروکنترلر، در بافری به صورت موقت ذخیره شود. برای این منظور آرایه‌ای به سایز 200 بایت به همراه متغیری برای نگه‌داری تعداد بایت ذخیره شده، تعریف کردیم.

 
uint8_t uart1_buf[200];
uint8_t bytes_in_buf = 0;

در ابتدا برنامه به خوبی کار می‌‎کرد. تا اینکه با بزرگ‌تر شدن برنامه ناگهان سر و کله‌ی رفتارهای عجیب پیدا شد. البته که ما خوش‌شانس بودیم که می‌توانستیم این رفتارهای عجیب را هنگام توسعه‌ی نرم‌افزار ببینیم. اوضاع می‌تواند به مراتب بدتر باشد، هنگامی که دستگاه شما توسط مشتری در حال استفاده است.

بعد از چندین روز بررسی بالاخره توانستیم علّت مشکل را پیدا کنیم. بزرگتر شدن برنامه باعث شده بود پردازنده دیرتر سراغ تابعی که مسئول خالی کردن بافر است، برود. در نتیجه گاهی اوقات متغیر bytes_in_buf بزرگتر از 199 می‌شد و در جایی از حافظه مقدار جدید را ذخیره می‌‎کرد که خارج از آرایه uart1_buf بود. یک راه ساده برای حل این مشکل می‌تواند چک کردن مقدار اندیس متغیر باشد:

 
if(bytes_in_buf < 200) {
    uart1_buf[bytes_in_buf] = uart_get_byte();
}

با اینکار دیگه مطمئن هستیم که خارج از محدوده‌ی آرایه را ناخواسته دستکاری نمی‌کنیم. شاید شما راه دیگری را انتخاب کنید، مهم نیست. نکته‌ی مهم این است که همیشه خطر این موضوع را هنگام کار با آرایه‌ها در نظر بگیرید.