خطاهای نحوی، منطقی، مربوط به کامپایل و خطاهای زمان اجرا چهار مورد از رایجترین خطاهای برنامه نویسی هستند. اما انواع خطا در برنامه نویسی شامل موارد دیگری نیز میشود که در ادامه به شکل کامل توضیح دادهایم. تجربه روبهرو شدن با خطاهای مختلف در زمان برنامه نویسی، یکی از بخشهای مهم فرایند توسعه نرمافزار است. بهترین توسعهدهندگان، آموختهاند که این باگها را به شکل مناسب و سادهای مدیریت کرده و به سرعت مشکلات ظاهر شده را حل کنند. بهترین برنامه نویسان کسانی نیستند که توانایی نوشتن برنامههای صددرصد بدون خطا را داشته باشند. یکی از معیارهای مهارت در برنامه نویسی، توانایی مدیریت و برطرف کردن خطاها است.
در این مطلب از مجله فرادرس درباره ۷ مورد از رایجترین انواع خطا در برنامه نویسی صحبت کردهایم و روش پیشگیری از روی دادن آنها و برطرف کردنشان را نیز بررسی کردهایم. در ابتدا تمام خطاهای ممکن معرفی شده و سپس همه را توضیح دادیم.
انواع خطا در برنامه نویسی چیست؟
خطاهای برنامه نویسی، بسته به زمان، مکان و حتی تکنولوژیهای مورد استفاده فرق میکنند. اما به شکل خلاصه در این مطلب ۱۰ مورد از رایجترین خطاهای برنامه نویسی را در فهرست زیر معرفی کردهایم.
- «خطاهای نحوی» (Syntax Errors)
- «خطاهای منطقی» (Logic Errors)
- «خطاهای مربوط به کامپایل» (Compilation Errors)
- «خطاهای زمان اجرا» (Runtime Errors)
- «خطاهای ریاضی» (Arithmetic Errors)
- «خطاهای منبع» (Resource Errors)
- «خطاهای رابط» (Interface Errors)
- «خطاهای پیوند دهنده» (Linker Errors)
- «خطاهای معنایی» (Semantic Errors)
- «خطاهای مربوط به عبور از محدودیت زمانی خاص» (Time Limit Exceeded Errors)
دانشمند فقید علوم کامپیوتر، آقای «ادسخر دیکسترا» (Edsger W. Dijkstra) گفته است که «اگر دیباگ کردن، فرایندی برای حذف باگها است، پس برنامه نویسی هم حتما فرایندی است که باگها را به وجود میآورد.» یعنی اینکه هر وقت کدنویسی میکنیم حتما خطاهایی هم وجود خواهند داشت.
یکی از روشهای بسیار مناسب برای سادهسازی عملیات مدیریت خطا و پیشگیری از بروز خطاهای زیاد، رعایت قوانین مربوط به کدنویسی تمیز است. زیرا در این صورت، به راحتی میتوانیم قطعه کدهای اشخاص دیگر یا قطعه کدهای گذشته خود را نیز درک و در صورت نیاز اصلاح کنیم. همچنین دیگران هم میتوانند کدهای نوشته شده ما را به راحتی متوجه شده و اصلاح کنند. برای رسیدن به این مهارت پیشنهاد میکنیم که فیلم آموزش کدنویسی تمیز Clean Code برای برنامه نویسی را از فرادرس مشاهده کنید. به منظور کمک به مخاطبان مجله، لینک این فیلم را در پایین نیز قرار دادهایم.
در ادامه مطلب تمام خطاهای فهرست بالا را یک به یک و به صورت منظم از اولین مورد شروع کرده و توضیح دادهایم.
خطاهای نحوی
زبانهای برنامه نویسی هم مانند زبانهای انسانی، دارای قواعد دستور زبانی مخصوص به خود هستند. اما انسانها میتوانند حتی بدون استفاده صحیح از دستور زبان و با به کار بردن کلمات شکسته نیز با یکدیگر ارتباط برقرار کنند. این نوع از ارتباط در بین کامپیوترها مجاز نیست. کامپیوترها نمیتوانند خطاهای نحوی و املایی را در زبانهای برنامه نویسی نادیده بگیرند. به این خطاها «خطای سینتکس» یا «Syntax Errors» گفته میشود.
برای مثال، فرض کنیم که سینتکس صحیح برای چاپ کردن رشته hello را در کادر زیر نوشتهایم.
ولی اگر برنامه نویس به صورت تصادفی، فراموش کند که در زمان نوشتن کد، یکی از پرانتزها را قرار دهد. در این صورت خطای سینتکس رخ داده و فرایند اجرای برنامه متوقف میشود.
روش جلوگیری از خطا
هرچقدر که مهارت افراد در برنامه نویسی افزایش پیدا کند، میزان رویدادن خطاهای سینتکس هم کاهش مییابد. سادهترین روش برای جلوگیری از بروز این خطاها و ایجاد مشکل در برنامه این است که در زمان کدنویسی دقت کرده و کدهای خود را هشیارانه بنویسم. اما اکنون بیشتر کد ادیتورها یا IDE-ها به صورت پیشفرض و خودکار دارای توانایی تشخیص خطای سینتکس هستند. این محیطهای کدنویسی، همزمان با روند توسعه برنامه، هر وقت با خطایی روبهرو شوند، بلافاصله به برنامه نویس اخطار میدهند.
چگونه از فرادرس برای آموزش برنامه نویسی کمک بگیریم؟
به غیر از شناخت انواع خطا در برنامه نویسی باید بدانیم روش کدنویسی هم در بروز یا مدیریت خطاها بسیار موثر است. بسیار مهم است که برنامه نویسی را از همان ابتدا به درستی یاد بگیریم. در ابتدا باید زبان مورد نظر را با توجه به اهداف ذهنی خود انتخاب کنیم. در حال حاضر زبانهای برنامه نویسی متنوعی وجود دارند. اما بعضی از این زبانها برای انجام نوع خاصی از پروژهها مناسبتر هستند. برای آشنایی با انواع زبانهای برنامه نویسی، میتوانید از فیلمهای فرادرس استفاده کنید. فرادرس به عنوان بزرگترین تولیدکننده محتوهای آموزشی کشور، فیلمهای خوبی را از سطوح مبتدی تا حرفهای طراحی و منتشر کرده است. بنابراین، تمام جویندگان علم میتوانند نیازهای خود را در فرادرس تأمین کنند.
لازم به اشاره است که بیشتر فیلمهای مربوط به دورههای مقدماتی و آشنایی با برنامه نویسی در فرادرس برای استفاده عموم مردم و به صورت رایگان منتشر شدهاند. چند مورد از این فیلمها آموزشی را در پایین معرفی کردهایم. در صورت نیاز با کلیک بر روی تصویر بالا میتوانید وارد صفحه اصلی این مجموعه آموزشی شده و فیلمهای بیشتر با سطوح علمی پیشرفتهتری را نیز مشاهده کنید.
خطاهای منطقی
«خطاهای منطقی» (Logic Errors) تقریبا مشکلترین خطاها در ردیابی و تعمیر هستند. در زمان رویدادن این خطاها، همهچیز به نظر سالم کار میکنند. فقط مسئله این است که برنامه کامپیوتر را طوری نوشتهایم که کارهای اشتباهی انجام دهد. در واقع، از لحاظ تکینکی برنامه صحیح و سالم است، اما نتایج با آن چیزی که انتظار میرود، تفاوت دارند.
برای مثال، اگر از قبل، نیازمندیهای برنامه را بررسی نکرده و کدها را طوری نوشتهایم که قدیمیترین کاربر سیستم را برگرداند – در حالی که نیاز به اطلاعات جدیدترین کاربر داریم – در این حالت گفته میشود که با خطای منطقی یا Logic Error روبهرو شدهایم.
یکی از مشهورترین مثالها برای این خطا در سال ۱۹۹۹ میلادی رخ داد. در آن سال، سازمان فضایی آمریکا «NASA» یکی از سفینههای فضایی خود را به دلیل اشتباه در محاسبات ریاضی گم کرد. این مسئله بخاطر تفاوتهایی بود که بین واحدهای اندازهگیری انگلیسی و آمریکایی وجود داشت. نرمافزار توسط یکی از این واحدهای اندازهگیری کدنویسی شده بود، اما باید به روش دیگری کار میکرد.
روش جلوگیری از خطا
بعد از نوشتن تستهای برنامه، برای تایید کردن منطق مورد استفاده در کدهای برنامه، باید آنها را به مالک محصول یا مدیر محصول نشان داد. در مثال بالا، کسی که با روال کار آشنایی کامل دارد باید متوجه این شود که برنامه نویس جزئیات مورد نیاز برای بدست آوردن جدیدترین کاربر را از دست داده است.
خطاهای مربوط به زمان کامپایل
بعضی از زبانهای برنامه نویسی نیاز به مرحله کامپایل دارند. کامپایل کردن در برنامه نویسی به این معنا است که کدهای نوشته شده به زبان سطح بالا باید تبدیل به کدهای زبانهای سطح پایین شوند. در این صورت، کامپیوتر میتواند این کدها را بهتر درک کند. «خطای مربوط به زمان کامپایل» (Compile Time Error) وقتی به وقوع میپیوندند که کامپایلر نمیداند، چطور باید کدهای نوشته شده را به کدهای زبان سطح پایین تبدیل کند.
در مثال مربوط به خطای سینتکس که بالاتر نمایش دادیم، اگر میخواستیم کد زیر را کامپایل کنیم، کامپایلر متوقف شده و پیغام خطایی را نشان میداد. در این پیغام خطا اعلام میشود که کامپایلر نمیداند چطور باید این کد را به کدهای زبان سطح پایین ترجمه کند. زیرا توقع دارد که بعد از علامت ‘ با کاراکتر پرانتز بسته ) روبهرو شود.
اگر نرمافزار طراحی شدهای دارای خطایی مربوط به زمان کامپایل باشد، اصلا امکان تست و راهاندازی نرمافزار وجود ندارد.
روش جلوگیری از خطا
مانند خطاهای مربوط به سینتکس، برای جلوگیری از بروز این خطاها هم بهترین وقت همان زمان کدنویسی است. اما به طور کلی، بهترین روش برای مدیریت این خطا آن است که دقیقا همزمان با متوجه شدن درباره وجود چنین خطاهایی، اقدام به رفع آنها بکنیم.
خطاهای مربوط به کامپایل بر روی تمام فایلهای پروژه و در زمان یکسانی روی میدهند. اگر تغییرات زیادی در کدها اعمال کرده و در نتیجه با تعداد زیادی از پیغامهای اخطار یا خطای کامپایلر روبهرو شویم، وضعیت بسیار اضطرابآوری به وجود میآید. اجرای کامپایلر به صورت مرحله به مرحله، باعث میشود که با سرعت بیشتری با بازخوردهای مورد نیاز درباره برنامه روبهرو شویم. بنابراین پیدا کردن مشکل و راه حل متناسب با آن به شکل بسیار سادهتری انجام میشود.
معمولا بیشتر خطاهای برنامه نویسی قابل پیشگیری هستند. زیرا بیشتر این اشتباهات بین برنامهنویسان مختلف مشترکاند. از طرف دیگر اشتباهات رایج در کدنویسی میتوانند منجر به ازکارافتادگیهای گسترده، دزدی اطلاعات، نفوذ و مشکلات زیاد دیگری در برنامه نهایی بشوند. برای آشنایی با رایجترین اشتباهات و آموزش رفع آنها در زمان کدنویسی میتوانید مطلب ۱۰ اشتباه رایج در کدنویسی و روشهای اجتناب از آنها را در مجله فرادرس مطالعه کنید.
خطاهای زمان اجرا
«خطاهای زمان اجرا» (Runtime Errors) وقتی روی میدهند که کاربری در حال کار با برنامه – بعد از نوشتن کدها و ارائه برنامه به کاربر نهایی برای استفاده – است. شاید کدها به شکل صحیح در کامپیوتر برنامه نویس کار کنند. اما از آنجا که ممکن است، بر روی وب سرور از کانفیگها و تنظیمات متفاوتی استفاده شده باشد، در عمل با نتیجه متفاوتی روبهرو شویم. یا شاید هم کاربر با برنامه به شکل خاصی تعامل کرده که منجر به بروز خطای زمان اجرا شده است.
فرض کنیم که سیستم طراحی شده، دادههای ورودی را توسط فرم دریافت میکند. بعد از آن برنامه تلاش میکند که اولین حرف الفبای نام کاربر را توسط کدی مانند کد زیر به حرف الفبای بزرگ انگلیسی تبدیل کند. در صورتی که کاربر فرم را بدون نام پر کرده و ارسال کند، برنامه با خطا روبهرو میشود.
خطاهای زمان اجرا، به شکل خاصی آزاردهنده هستند. زیرا این خطاها به طور مستقیم بر روی کاربر نهایی و مصرف کننده اثر میگذارند. برعکس بقیه خطاها که میتوان در زمان کدنویسی کشف و برطرف کرد، این نوع از خطاها در زمان اجرای برنامه روی میدهند. در نتیجه میتوانند تجربه کاربری بدی را برای کاربران نهایی ایجاد کرده و از تکمیل کار آنها جلوگیری کنند.
روش جلوگیری از خطا
برای جلوگیری از روی دادن این خطاها، اول از همه باید از داشتن سیستم اعلام خطای مناسب مطمئن شد. چنین سیستمهایی خطاهای زمان اجرا را تشخیص داده و به صورت خودکار در سیستم گزارشدهی برنامه، وجود باگها را اعلام میکنند. باید هر کدام از این گزارشهای وجود باگ را به چشم فرصتی برای آموزش بیشتر ببینید. در این صورت، میتوانید از رویدادن چنین خطاهایی در آینده جلوگیری کنید.
روش دوم، استفاده از فریمورکها است. استفاده از فریم ورکها و کدهای محافظت شده توسط جامعه کاربری آن زبان یا فریمورک خاص، یکی از بهترین روشها برای کاهش «خطاهای زمان اجرا» (Runtime Errors) است. از آنجا که این کدها در پروژهای زیادی استفاده شدهاند، به احتمال زیاد برنامه نویسانی از قبل به دفعات با مشکلات آن روبهرو شده و بیشتر خطاها و مشکلات کدها را در طول زمان حل کردهاند.
خطاهای ریاضی
«خطاهای ریاضی» (Arithmetic Errors) یکی دیگر از انواع خطا در برنامه نویسی هستند. این نوع از خطاها نوعی از خطاهای منطقیاند که شامل مسائل ریاضی میشوند. به عنوان مثال معمولی میتوان به انجام معادله تقسیم اشاره کرد. در تقسیم، امکان اجرای این عملیات بر روی صفر وجود ندارد. تقسیم هر عددی بر صفر در کامپیوتر، منجر به بروز خطا در برنامه میشود. تعداد خیلی کمی از مردم عملیات «۵ تقسیم بر ۰» را مینویسند، اما شاید به این مسئله توجه نکردهایم که در صورت متغیر بودن مخرج تقسیم، ممکن است که گاهی از اوقات در طول عملیات برنامه، این متغیر برابر با صفر شود. در نتیجه این خطا روی خواهد داد.
در کد بالا اگر متغیر ages.min برابر با صفر شود، اجرای این کد قطعا باعث بروز خطا میشود.
روش جلوگیری از خطا
همینطور که در بخشهای بالایی اشاره کردیم، این خطاهای ریاضی میتوانند منجر به بروز خطاهای منطقی یا حتی خطاهای زمان اجرا نیز شوند. برای مثال، خطای تقسیم بر صفر یکی از خطاهای زمان اجراست که باعث توقف اجرای برنامه میشود.
برای جلوگیری از رویدادن این خطاها میتوان از نوع خاصی از تستهای نرم افزار به نام تستهای عملکردی استفاده کرد. وجود تستهای عملکردی که همیشه شامل موارد بحرانی مانند صفر و اعداد منفی هستند، یکی از بهترین روشها برای شناسایی این خطاها و در صورت نیاز رفع آنها است.
در فرایند تستنویسی، برای اطمینان از عملکرد صحیح، کدهای برنامه آزمایش میشوند. این مهارت، به عنوان یکی از مهارتهای ضروری برنامهنویسان به شمار میرود. زیرا تستنویسی باعث سادهتر شدن توسعه و نگهداری برنامهها شده و در نتیجه، زمان و هزینه مرتبط با تعمیر خطاها را کاهش میدهد. برای حرفهای شدن در این زمینه و در صورتی که با زبان PHP کار میکنید، پیشنهاد میکنیم که فیلم آموزش تست نویسی در زبان برنامه نویسی PHP برای شناسایی و رفع خطاهای احتمالی در کدها را از فرادرس مشاهده کنید. لینک مربوط به این فیلم را در پایین نیز قرار دادهایم.
خطاهای مربوط به کمبود منابع
کامپیوتری که برنامههای خود را در آن توسعه داده یا اجرا میکنیم، مقدار ثابتی از انواع منابع را برای اجرای برنامهها تخصیص میدهد. اگر چیزی در کدها باشد که کامپیوتر را مجبور به اختصاص منابع بیشتر کند، احتمال روبهرو شدن با «خطای منبع» (Resource Error) وجود دارد.
اگر به شکل تصادفی، حلقهای نوشتهایم که کدها قادر به خارج شدن از آن نیستند، ناگهان با کمبود منابع روبهرو میشویم. در مثال زیر، حلقه while دائما به افزودن عناصر جدید به آرایه ادامه میدهد. در نتیجه بعد از گذشت مدت زمان محدودی از اجرای کد زیر ناگهان با کمبود فضا در حافظه کامپیوتر روبهرو خواهیم شد.
پیدا کردن خطاهای منبع میتواند سخت باشد. زیرا معمولا کامپیوتری که عملیات توسعه را بر روی آن انجام میدهیم، قویتر از سیستم یا سروری است که کدهای نوشته شده باید بر روی آن اجرا شوند. همچنین شبیهسازی استفادههایی که در دنیای واقعی از نرمافزار میشود، بر روی کامپیوتر اداری معمولا سخت است.
روش جلوگیری از خطا
وجود سیستم گزارشدهی خوب درباره میزان استفاده از منابع در سرورهای اینترنتی، کدهایی را علامتگذاری میکند که در طول زمان به میزان خیلی زیادی از انواع منابع استفاده میکنند.
خطاهای منبع، مثالی از انواع خطاها در برنامه نویسی هستند که معمولا بهتر است بهجای تیمهای توسعه و کدنویسی، توسط تیمهای عملیات برطرف شوند.
ابزارها و سرویسهای زیادی برای انجام عملیات Load-Testing در دسترس هستند که با کمک آنها میتوان رفتار کدها را در شرایط فشار کاری بالا – استفاده توسط چندین کاربر مختلف به صورت همزمان – بررسی کرد. در این ابزارها برای دیدن نتایج کار برنامه در شرایط مختلف میتوانید مشخصات تستها را تغییر دهید.
خطاهای رابط
«خطای رابط» (Interface Errors) زمانی روی میدهند که برنامه نوشته شده به شکلی متفاوت از آنچه در نظر داشتیم، استفاده شود. بیشتر نرمافزارها از قوانینی به نام استاندارهای تولید نرمافزار پیروی میکنند. اگر دادههایی که برنامه میگیرد با قوانین و استاندارهای تعریف شده همخوانی نداشته باشد، احتمال بروز خطای Interface وجود دارد.
برای مثال، اگر در برنامه نوشته شده API-هایی وجود داشته باشند که نیاز به استفاده از پارامترهای خاصی دارند. ولی در عوض پارامترهای دیگر و نامرتبطی به آنها ارسال شدهاند، خطای رابط به وجود میآید.
اگر چنین موقعیتهایی به درستی مدیریت نشوند، این نوع از خطاها ممکن است مانند خطایی در کدها در نظر گرفته شوند. حتی با اینکه مشکل اصلی در کاربری است که API کدهای برنامه را فراخوانی کرده، بازهم شناسایی و رفع مشکل، سخت است. زیرا در اثر ایجاد چنین خطاهایی برای هر دو طرف کاربر و برنامه نویس سردرگمی و ابهام ایجاد میشود.
روش جلوگیری از خطا
داشتن مستندات واضح و مدیریت صحیح این نوع از خطاها به برنامه کمک میکند که کاربر را از مشکل اصلی مطلع کند. این روش، بهترین مدیریت مواجه با «خطای رابط» (Interface Errors) است. میتوانیم به کاربر پیامی با مضمون «عدم ارائه اطلاعات صحیح و کافی برای رسیدگی به درخواست» ارسال کنیم. درک صحیح خطا و نمایش پیغام مرتبط به کاربر، مشکلات مربوط به پشتیبانی از برنامه را کاهش داده و تجربه کاربری بهتری را ارائه میدهد. زیرا کاربران متوجه مشکل شده و میدانند با استفاده از چه اطلاعات و تغییراتی مشکل حل میشود.
اگر این مشکلات شناسایی نشده و به درستی مدیریت نشوند، بازخورد غلطی به کاربر ارسال میشود. سپس خطاهای رابط مانند خطاهای زمان اجرا در برنامه دیده شده و به همین صورت هم در گزارشات مربوط به خطاها درج میشوند. در نتیجه مجبور به انجام بررسیهای بسیار زیاد و غیرضروری در کدها میشویم.
خطاهای پیونددهنده
«خطاهای پیونددهنده» (Linker Errors) در برنامه نویسی زمانی رخ میدهند که کامپایلر برای اتصال بخشهای مختلف برنامه یکسانی مانند فایلهای اشیاء یا کتابخانهها به همدیگر تلاش میکند. اما برای تطبیق دادن نمادها یا آدرسهای مرجع به مشکل برمیخورد. این نوع از خطا معمولا بیشتر در زبانهای C یا ++C رخ میدهند. اغلب اوقات این خطا وقتی روی میدهد که کامپایلر تلاش میکند چندین فایل شیء یا کتابخانه مختلف را با هم ترکیب کند تا فایل اجرایی مجزایی ایجاد شود. اما در زمان اجرای این فرایند برای مشخص کردن مرجع نمادهای – توابع، متغیرها و اشیاء – مختلف یا ارتباطات بین آنها به مشکلات مختلفی روبهرو میشود.
در فهرست زیر، رایجترین موقعیتهای منتهی به «خطای پیوند دهنده» را جمعآوری کردهایم.
- مورد اول: این خطا زمانی روی میدهد که کامپایلر نمادهای مانند اشیاء، متغیرها و توابع را پیدا کرده است که در کدها استفاده شدهاند، اما در هیچ کدام از فایلها یا کتابخانههای متصل شده تعریف نشدهاند.
- مورد دوم: کامپایلر با چندین تعریف مختلف از نماد یکسان در فایلها یا کتابخانههای متفاوتی برخورد میکند.
- مورد سوم: از دست دادن یا ناسازگار بودن پیشنیازهای فعالیت کتابخانههای مختلف. برای مثال، بعضی از کتابخانهها برای انجام فعالیتهای خود نیاز به استفاده از کتابخانههای دیگر یا نسخههای خاصی از آن کتابخانهها دارند.
در کادر زیر، مثالی از «خطاهای پیونددهنده» (Linker Errors) را در زبان ++C کدنویسی کردهایم.
اگر کدهای بالا را به صورت دو فایل مجزا از هم – فایل اول تا خط ۸ و فایل دوم از خط ۹ به بعد – بنویسیم. سپس به صورت جداگانه کامپایل کرده و بهم متصل کنیم، با خطای پیوند دهنده روبهرو میشویم. زیرا پیوند دهنده این فایلها در زمان کامپایل موفق به پیدا کردن تعریف تابع printMessage() در فایل main.cpp نمیشود.
برای برطرف کردن خطای فایلهای بالا، باید مطمئن شویم که هردو فایل منبع با موفقیت کامپایل شده به یکدیگر متصل شدهاند. این کار را از طریق کامپایل کردن هردو فایل و سپس برقرار کردن ارتباط بین آنها انجام بدهیم.
g++ -c main.cpp -o main.o g++ -c functions.cpp -o functions.o g++ main.o functions.o -o my_program
روش جلوگیری از خطا
برای حل کردن خطای پیونددهنده یا همان Linker Error در برنامه نویسی، باید مراحل زیر را به شکل گامبهگام طی کنیم.
- ابتدا کار خود را با اطمینان از این شروع میکنیم که تمام نمادها در کد باید به خوبی تعریف شده یا در کدهای منبع یا کتابخانههای پیوند زده شده با فایل کد اصلی، پیادهسازی شده باشند.
- حتما برای جلوگیری از وجود تعریفهای تکراری از متغیر، تابع یا شیءها، کدها را بررسی کنیم.
- سپس انواع تداخلات احتمالی در تعاریف را با حذف، ترکیب یا تغییر و تثبیت کدهای نوشته شده اضافی بر طرف کنیم.
- مطمئن شویم که همه کتابخانهها و وابستگیهای مورد نیاز به شکل صحیحی متصل شده و در دسترس «پیونددهنده» (Linker) قرار دارند.
- به انواع گزینههای کامپایلر و پرچمهای آن توجه کنیم. این موارد باید با احتیاجات عملیاتی برنامه نوشته شده به شکل صحیح منطبق باشند.
خطاهای معنایی
«خطاهای معنایی» (Semantic Errors)، شبیه به خطاهای منطقی هستند. زیرا خطاهای معنایی زمانی روی میدهند که اشتباه در رفتار یا منطق برنامه است. اما نمیتوان خطاهای معنایی را به شکل دقیق با خطاهای منطقی یکسان دانست. خطای معنایی اشاره به خطاهایی دارد که در معنا یا تفسیر کد به وجود میآیند. این نوع از خطاها باعث میشوند که کدها رفتار مورد انتظار از خود را نشان ندهند. پیدا کردن مرجع این نوع از خطاها معمولا سختتر از پیدا کردن خطاهای سینتکس یا منطقی است.
به عنوان چند مثال برای توضیح بهتر خطاهای معنایی میتوان به موارد فهرست شده در زیر اشاره کرد.
- برداشت یا تفسیر اشتباه از نیازمندیها یا ویژگیهای خاص تعریف شده در برنامه
- وجود نقص در طراحی یا پیادهسازی الگوریتم
- تخصیص یا تغییر مقادیر ذخیره شده در متغیرها با انواع ناسازگار داده – برای مثال به متغیری که باید حاوی عدد صحیح باشد، مقدار کاراکتری آن را اختصاص بدهیم.
- استفاده نامناسب از API-ها یا کتابخانههای خارجی که با روش کار آنها به خوبی آشنا نبوده یا روش اتصال صحیح آنها را به کدهای خود بلد نیستیم.
در کادر زیر، مثال سادهای از بروز «خطاهای معنایی» (Semantic Errors) را در کدهای پایتون پیادهسازی کردهایم.
خطای معنایی موجود در کدهای بالا، به احتمال زیاد در طول زمان کامپایل یا اجرای آزمایشی کدها مشخص نمیشود. زیرا کدها هنوز بدون اعلام هیچ نوع خطای سینتکس یا استثناهای مربوط به زمان اجرا به کار خود ادامه میدهند. هرچند که به دلیل اشتباه در فرمول نوشته شده در تابع، مقدار ناحیه محاسبه شده غلط است. در نتیجه نتایج بدست آمده توسط کدهای بالا صحیح نیستند.
برای تعمیر این خطای معنایی، باید از تابع صحیح مربوط به محاسبه مساحت در دایره به شکل π * radius * radius در تابع calculate_circle_area استفاده کنیم. در نتیجه کد بالا به شکل زیر نوشته میشود.
با استفاده از فرمول صحیح، تابع به شکل دقیقی محاست دایره را با توجه به اندازه شعاع داده شده محاسبه میکند. در نتیجه خطای معنایی درون کدها برطرف شده و نتایج صحیحی توسط تابع تولید میشوند.
روش جلوگیری از خطا
از آنجا که معمولا خطاهای معنایی به دلیل وجود اشتباهات کوچک در درک روش صحیح کار کدها به وجود میآیند، فرایند کشف و برطرف کردنشان سخت است.
یکی از بهترین روشها برای جلوگیری از بروز خطاها معنایی استفاده از نامهای با معنا و توصیفی برای متغیرها و توابع است. همچنین بسیار مهم است که تمام نیازمندیهای برنامه را قبل از شروع به کدنویسی درک کنیم. در صورت وجود هر نوع ابهام با سایر افراد دخیل در فرایند کار، مشورت کنید. با این کار مطمئن میشوید درکی که از وظیفه خود دارید با انتظارات همکارن و باقی اعضای تیم توسعه یکسان است.
به سبک کدنویسی ثابتی، مقید شوید و از استاندارهای برنامه نویسی شناخته شده و بهترین الگوهای معرفی شده برای کدنویسی، پیروی کنید. این مسئله فرایند درک کدها را برای همه سادهتر کرده و احتمال کجفهمی کدها یا تفسیر اشتباه آنها توسط دیگر توسعهدهندگان را نیز کاهش میدهد.
روش اصولی یادگیری برنامه نویسی با فرادرس
شناخت انواع خطا در برنامه نویسی و دانستن روش کشف و مدیریت آنها برای همه افراد مبتدی و حرفهای لازم است. با استفاده از آموزشهای پیشرفتهتر میتوانیم کدهایی با خطای کمتر و با امکان خطایابی سادهتر بنویسیم. از طرفی، آموزشهای اصولی برنامه نویسی نیازمند صرف هزینه و زمان زیادی هستند. به همین دلیل وبسایت فرادرس، همیشه به دنبال راهی بوده که بتواند با کیفیتترین آموزشها را تولید کرده و با هزینههای مقرونبهصرفه در اختیار جویندگان علم قرار دهد. استفاده از فیلمهای آموزشی فرادرس از جهات مختلف مانند هزینه، زمان و غیره نسبت به کلاسهای حضوری، منطقیتر است. این فیلمها همیشه قابلیت بازبینی مجدد و مرور هم دارند.
در مجموعه آموزش برنامه نویسی مقدماتی تا پیشرفته فرادرس درباره زبانهای برنامه نویسی مختلف، فیلمهای آموزشی متنوعی را تهیه کردهایم. در قسمت پایین، چند مورد از فیلمهای سطح بالا و تخصصی مربوط به زبانهای برنامه نویسی مختلف را معرفی کردهایم.
خطاهای مربوط به عبور از محدودیت زمانی خاص
«خطای مربوط به عبور از محدودیت زمانی خاص» (Time Limit Exceeded Error) را به نام «خطای پایان فرصت» (Timeout Error) نیز میشناسند. این خطا زمانی روی میدهد که برنامه یا عملیات خاصی در آن، برای به پایان رساندن کار خود نسبت به مقدار مجاز، زمان بیشتری را صرف میکند. این خطا معمولا در سناریوهایی روی میدهد که در آنها برای انجام وظایف خاص یا همه وظایف، محدوده زمانی مشخصی تعیین شده است. به عنوان مثالهایی از این نوع عملیات با محدودیت زمانی میتوان به موارد زیر اشاره کرد.
- درخواستهای ارسال شده در شبکههای دارای محدودیت زمان پاسخگویی
- الگوریتمهای محاسباتی
- عملیات سیستمی – مربوط به سیستم عامل
دلایل روی دادن خطا
خطای مربوط به عبور از محدودیت زمانی خاص، معمولا در شرایط زیر، روی میدهد.
- وقتی که برنامه یا عملیاتی برای اجرای کامل کار خود، بیش از زمان مجاز، وقت صرف کند، خطای Time Limit Exceeded روی میدهد. صرف زمان طولانی برای انجام کار، معمولا بخاطر مواردی مانند استفاده از الگوریتمهای ناکارآمد، انتظار و رقابت برنامهها برای تخصیص منابع یا دادههای ورودی با اندازههای بزرگ – که زمان زیادی برای پردازش آنها باید صرف شود – روی میدهد.
- یکی دیگر از دلایل بروز خطای مربوط به عبور از محدودیت زمانی وقتی است که وظیفهای از ادامه اجرا منع شده یا به مدت نامحدود در صف انتظار دسترسی به منبع یا عملیات خاصی گیر کرده است. این مسئله معمولا به دلیل مشکلات مربوط به همگامسازی، بنبستهای پردازشی یا تاخیرهای غیرمنتظره در دسترسی به منابع مورد نیاز روی میدهد.
- وقتی که زمان مورد استفاده برای عملیات ارسال و دریافت اطلاعات در شبکه با تاخیر روبهرو شده یا به پایان میرسد. این مسئله به دلایلی مانند ترافیک بالا، از دست رفتن بستههای اطلاعاتی یا زمان پاسخگویی آهسته توسط سرورها یا سرویسهای ریموت روی میدهد.
- معمولا برای تکمیل وظایف در کامیپوترها چهارچوب زمانی مشخص میشود. فرسودگی و خستگی منابع، مانند کمبود حافظه، زمان در دسترس بودن سی پی یو یا سایر منابع مورد نیاز باعث میشوند که زمان تکمیل بعضی از عملیات از چهارچوب مشخص شده فراتر برود. این مسئله نیز یکی دیگر از دلایل بروز «Time Limit Exceeded Error» است.
- کمبود منابع سختافزاری، تنظیمات غلط شبکه یا مشکلات مربوط به سرویسهای طرف سومی که برنامه برای کار به آنها تکیه کرده هم جزو دلایل روبهرو شدن با خطای مربوط به عبور از محدودیت زمانی خاص است.
در کادر پایین، برای نمایش خطای مربوط به عبور از محدودیت زمانی، مثالی را با کدهای پایتون پیادهسازی کردهایم. در این مثال از تابع سادهای استفاده کردهایم که عملیات محاسباتی فشردهای را انجام میدهد.
در کدهای بالا، تابع compute_factorial مقدار فاکتوریل عددی را که مشخص شده محاسبه میکند. در زمان محاسبه مقدار فاکتوریل اعداد بسیار بزرگ – برای مثال ۱۰۰۰۰ – عملیات برای تکمیل فرایند خود به میزان چشمگیری زمان صرف خواهد کرد.
در مثال بالا، زمان سپری شده عملیات را با استفاده از کتابخانه time اندازهگیری میکنیم. با این کار میخواهیم فرایندی را شبیهسازی کنیم که منجر به خطای «عبور از محدوده زمانی مشخص» میشود. به این منظور، زمان قبل و بعد از اجرای عملیات محاسباتی را اندازه گرفته و اختلاف آنها را به دست میآوریم. اگر میزان زمان صرف شده از محدوده زمانی از پیش تعیین شده – که در این مثال ۱ ثانیه است – بیشتر بود، آن را به عنوان خطای «عبور از محدوده زمانی مشخص شده» در نظر گرفته و پیغام خطای مناسبی را نمایش میدهیم.
توجه: در پیغام خطا باید سعی کنیم که به شکل واضح به علت بروز خطا اشاره کنیم.
برای دیدن روش رفتار برنامه بالا، در موقعیتهای مختلف میتوانیم به شکل دلخواه مقدار عدد ورودی یا محدوده زمانی را تغییر دهیم. با دادن عدد ورودی بزرگتر یا کاهش دادن مقدار محدوده زمانی مجاز احتمال روبهرو شدن با خطای «Time Exceeded Error» وجود دارد.
روش جلوگیری از خطا
برای برطرف کردن خطاهای عبور از محدوده زمانی، باید بر روی افزایش کیفیت و کارایی الگوریتمها کار کرد. با داشتن الگوریتمهای بهینه زمان بندی، زمان مورد نیاز برای انجام پردازش به حداقل ممکن رسیده و احتمال روبهرو شدن با خطای مربوط به زمان به کم میشود. برای محدود کردن مقدار زمان مورد نیاز اجرای عملیات مختلف از محدودههای زمانی استفاده کنید. با این کار از مسدود شدن اجرای عملیات یا گرفتاری در صف انتظار نامحدود جلوگیری میشود.
به شکل مداوم، کارایی سیستم و منابع مختلف را برای پیدا کردن بخشهای آهسته یا مشکلات احتمالی نظارت کنید. زیرا بیتوجهی به آن مشکلات و بخشها میتواند منجر به بروز خطای عبور از محدوده زمانی شود. با استفاده از استراتژیهای عقب نشینی یا تلاش مجدد، میتوانید خرابیها یا تاخیرهای موقتی را مدیریت کنید. در نتیجه خطای محدودیت زمانی یا اثرات مخرب آن به میزان زیادی کاهش پیدا میکنند.
در نهایت هم باید اشاره کنیم که تنظیمات مربوط به محدوده زمانی بر اساس نیازهای خاصی انجام میشوند. بنابراین باید به ویژگیهای سیستم و اپلیکیشن خود نیز توجه کنیم.
استفاده از ابزارهای تحلیل کد ایستا برای کم کردن خطاها
استفاده از ابزارهای تحلیل کد ایستای یکپارچه در فرایند توسعه برنامهها یکی از بهترین روشها برای کاهش خودکار اخطارهای برنامه نویسی است. قبل از اینکه مشکلات برنامه بر روی تولید محصول اثر منفی بگذارند، این ابزارها به برنامه نویسان برای پیدا کردن آنها کمک میکنند. علاوه براین باعث صرفهجویی در وقت برنامه نویسها نیز میشوند. براساس گزارش «وضعیت کیفیت نرمافزار در سال ۲۰۲۴» (2024 State of Software Quality) ۵۸٪ برنامه نویسان گفتهاند که بزرگترین چالش در طی زمان بازبینی کدها مربوط به کمبود زمان است.
ابزارهای تحلیل کد ایستا برای کم کردن خطاها به توسعهدهندگان کمک میکنند که خطاها را در اولین فرصت و در فرایند توسعه شناسایی کرده و برطرف کنند. با اضافه کردن ابزارهای تحلیل کد ایستا به جریان کاری، تیمهای توسعه نرمافزار میتوانند کیفیت کدها را ارتقا داده، فرایند کار تیمی سادهتر شده و نرمافزارهای قابل اتکاتری را به مشتری تحویل دهند.
جمعبندی
با اینکه خوشبختانه دههها از زمان نیاز به استفاده از کارتهای پانچ گذشته است. اما هنوز هم مهندسی نرمافزار کار سختی است. زیرا اغلب اوقات نیازمندیهای تولید – در مراحل اولیه و پیش از شروع کار – مبهم هستند و کدها دائما تغییر میکنند. نباید از وجود خطا در کدها ناراحت شد. زیرا این اتفاق برای همه برنامه نویسان رخ میدهد. حتی بزرگترین برنامهها هم دچار باگ میشوند. مهم این است که با تمرین و مرور اطلاعات مطالبی مانند مطلب بالا، تجربه خود را افزایش داده و در مدیریت و برطرف کردن خطا حرفهای شویم.
وجود انواع خطا در برنامه نویسی اجتنابناپذیر است. هرچند به مرور زمان در تشخیص خطا ارتقا پیدا میکنیم، اما هرگز بدون خطا نخواهیم شد. در این مطلب از مجله فرادرس تلاش کردیم که انواع خطا در برنامه نویسی را معرفی کرده و چند مورد از رایجترین خطاهای ممکن را به شکل واضح توضیح دهیم.
source