-
فرشید پوشنده
1405/05/24
-
24 مرداد 1405
بازگشت به: آموزش برنامه نویسی c++ سی پلاس پلاس
۰.۱۱ — پیکربندی کامپایلر: سطوح هشدار و خطا
هنگامی که برنامههای خود را مینویسید، کامپایلر بررسی میکند که آیا قوانین زبان C++ را رعایت کردهاید (با فرض اینکه افزونههای کامپایلر را طبق درس ۰.۱۰ — پیکربندی کامپایلر: افزونههای کامپایلر غیرفعال کردهاید). اگر کاری انجام دادهاید که به طور قطع قوانین زبان را نقض میکند، برنامه شما نادرست (Ill-Formed) محسوب میشود.
در بیشتر موارد، وقتی کامپایلر با نوعی مشکل مواجه میشود، یک پیام تشخیصی (Diagnostic Message) (که اغلب به اختصار تشخیصی (Diagnostic) نامیده میشود) صادر میکند. استاندارد C++ تعیین نمیکند که پیامهای تشخیصی چگونه باید طبقهبندی شوند، چگونه بیان شوند، یا این مسائل چگونه باید بر کامپایل برنامه تأثیر بگذارند. با این حال، کامپایلرهای مدرن به طور معمول موارد زیر را پذیرفتهاند:
یک خطای تشخیصی (Diagnostic Error) (یا به اختصار خطا (Error)) به این معنی است که کامپایلر تصمیم گرفته است کامپایل را متوقف کند، زیرا یا نمیتواند ادامه دهد یا خطا را به اندازه کافی جدی میداند که متوقف شود. خطاهای تشخیصی تولید شده توسط کامپایلر اغلب خطاهای کامپایل (Compilation Errors)، خطاهای کامپایلر (Compiler Errors) یا خطاهای کامپایل (Compile Errors) نامیده میشوند.
یک هشدار تشخیصی (Diagnostic Warning) (یا به اختصار هشدار (Warning)) به این معنی است که کامپایلر تصمیم گرفته است کامپایل را متوقف نکند. در چنین مواردی، مشکل نادیده گرفته میشود و کامپایل ادامه مییابد.
نکته کلیدی
کامپایلرها تعیین میکنند که آیا یک مشکل غیرمسدودکننده (غیرجدی) یک هشدار است یا یک خطا. اگرچه معمولاً در طبقهبندی خود همسو هستند، اما در برخی موارد، کامپایلرها ممکن است با یکدیگر همنظر نباشند — به طوری که یک کامپایلر برای یک مشکل خاص خطا صادر کند و کامپایلر دیگری برای همان مشکل هشدار صادر کند.
برای کمک به شما در شناسایی محل مشکل، پیامهای تشخیصی معمولاً شامل نام فایل و شماره خطی هستند که کامپایلر مشکل را در آنجا پیدا کرده است، و همچنین متنی درباره آنچه انتظار میرفته در مقابل آنچه پیدا شده است. ممکن است مشکل اصلی در همان خط باشد یا در خط قبلی. پس از رفع مشکلی که باعث ایجاد تشخیص (Diagnostic) شده است، میتوانید دوباره کامپایل کنید تا ببینید آیا دیگر پیام تشخیصی مربوطه تولید نمیشود یا خیر.
در برخی موارد، کامپایلر ممکن است کدی را شناسایی کند که قوانین زبان را نقض نمیکند، اما معتقد است که میتواند نادرست باشد. در چنین مواردی، کامپایلر ممکن است تصمیم بگیرد که یک هشدار (Warning) به عنوان اخطاری به برنامهنویس صادر کند که چیزی به نظر نادرست میرسد. چنین مسائلی یا با رفع مشکلی که هشدار به آن اشاره میکند، یا با بازنویسی خطوط کد مورد نظر به گونهای که دیگر هشدار تولید نشود، قابل حل هستند.
برای خوانندگان پیشرفته
ما مثالی از یک دستور (Statement) را نشان میدهیم که از نظر فنی قانونی است اما کامپایلرهای مدرن آن را مشکوک میدانند، در درس ۷.۷ — پیوند خارجی (External Linkage) و اعلانهای پیشین متغیرها (Variable Forward Declarations).
در موارد نادر، ممکن است لازم باشد به صراحت به کامپایلر بگوییم که یک هشدار خاص را برای آن خط کد خاص تولید نکند. C++ از یک روش رسمی برای انجام این کار پشتیبانی نمیکند، اما بسیاری از کامپایلرهای جداگانه (از جمله Visual Studio و GCC) راهحلهایی (از طریق دستورات غیرقابلحمل #pragma) برای غیرفعال کردن موقت هشدارها ارائه میدهند.
بهترین روش
اجازه ندهید هشدارها انباشته شوند. آنها را به محض مواجهه با آنها (انگار که خطا هستند) برطرف کنید. در غیر این صورت، ممکن است یک هشدار درباره یک مشکل جدی در میان هشدارهای مربوط به مسائل غیرجدی گم شود.
لینکر نیز ممکن است در صورت بروز مشکلی که در حین لینک کردن رخ میدهد و قابل حل نیست، خطاهای تشخیصی تولید کند.
افزایش سطوح هشدار (Warning Levels)
بهطور پیشفرض، بیشتر کامپایلرها فقط دربارهٔ واضحترین مسائل، هشدار تولید میکنند. با این حال، میتوانید از کامپایلر خود بخواهید که در ارائهٔ هشدارها قاطعتر عمل کند، و به طور کلی ایدهٔ خوبی است که این کار را انجام دهید.
بهترین روش
سطوح هشدار خود را افزایش دهید، به ویژه در زمانی که در حال یادگیری هستید. اطلاعات تشخیصی اضافی ممکن است به شناسایی اشتباهات برنامهنویسی که میتوانند باعث خرابی برنامه شما شوند، کمک کند.
برای کاربران Visual Studio
برای افزایش سطوح هشدار خود، روی نام پروژه خود در پنجره Solution Explorer کلیک راست کرده و سپس Properties (خواص) را انتخاب کنید:
از پنجره Project (پروژه)، ابتدا مطمئن شوید که فیلد Configuration (پیکربندی) روی All Configurations (همه پیکربندیها) تنظیم شده است.
سپس برگه C/C++ > General (عمومی) را انتخاب کرده و Warning Level (سطح هشدار) را روی Level4 (/W4) (سطح ۴) تنظیم کنید.
توجه: گزینه EnableAllWarnings (/Wall) را انتخاب نکنید، در غیر این صورت در میان هشدارهای تولید شده توسط کتابخانه استاندارد C++ مدفون خواهید شد.
Visual Studio بهطور پیشفرض هشدارهای تبدیل signed/unsigned را غیرفعال میکند، و این هشدارها مفید هستند، بنابراین اگر از Visual Studio 2019 یا جدیدتر استفاده میکنید، بیایید آنها را فعال کنیم:
از برگه C/C++ > Command Line، در بخش Additional Options، عبارت /w44365 را اضافه کنید. این به کامپایلر میگوید که هشدارهای تبدیل signed/unsigned را در سطح هشدار ۴ (که در بالا فعال کردید) فعال کند.
از برگه C/C++ > External Includes، External Header Warning Level را روی Level3 (/external:W3) تنظیم کنید. این به کامپایلر میگوید که هدرهای کتابخانه استاندارد را در سطح هشدار ۳ (به جای ۴) کامپایل کند تا کامپایل آن هدرها این هشدار را ایجاد نکند.
برگه “External Includes” در تصویر بالا نشان داده نشده است، اما در VS Community 2019 یا جدیدتر بین برگههای “Browse Information” و “Advanced” ظاهر میشود. به این لینک مراجعه کنید، که شامل عکس اخیری از کادر محاورهای حاوی برگه “External Includes” است.
اگر موارد فوق به درستی تنظیم شده باشند، کامپایل برنامه زیر باید هشدار C4365 را ایجاد کند:
1 void foo(int)
2 {
3 }
4
5 int main()
6 {
7 unsigned int x { 5 };
8 foo(x);
9
10 return 0;
11 }
اگر هشدار را مشاهده نمیکنید، هر دو برگه Output (خروجی) و Error List (فهرست خطاها) را بررسی کنید (در صورت وجود).
برای کاربران Code::Blocks
از منوی Settings > Compiler > Compiler settings، گزینههایی که با -Wall، -Weffc++ و -Wextra مرتبط هستند را پیدا کرده و آنها را علامت بزنید:
سپس به برگه Other compiler options (سایر گزینههای کامپایلر) بروید و عبارت -Wconversion -Wsign-conversion را به ناحیه ویرایش متن زیر اضافه کنید:
توجه: پارامتر -Werror در زیر توضیح داده شده است.
برای کاربران gcc
گزینههای زیر را به خط فرمان خود اضافه کنید:
-Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion
برای کاربران VS Code
فایل tasks.json را باز کنید، عبارت “args” را پیدا کنید، و سپس خط “${file}” را در آن بخش پیدا کنید.
بالای خط “${file}” ، خطوط جدید حاوی دستورات زیر (هر کدام در یک خط) اضافه کنید:
1 "-Wall",
2 "-Weffc++",
3 "-Wextra",
4 "-Wconversion",
5 "-Wsign-conversion",
رفتار با هشدارها مانند خطا (Treat Warnings as Errors)
همچنین امکانپذیر است که به کامپایلر خود بگویید با تمام هشدارها مانند خطا رفتار کند (در این صورت، اگر کامپایلر هر گونه هشدار پیدا کند، کامپایل را متوقف میکند). این راه خوبی برای اجرای توصیهی مبنی بر اینکه باید همهی هشدارها را برطرف کنید، است (اگر خودتان انضباط کافی ندارید، که اکثر ما نداریم).
بهترین روش
گزینهٔ «Treat warnings as errors» (رفتار با هشدارها مانند خطا) را فعال کنید. این کار شما را مجبور میکند تا تمام مسائلی را که باعث ایجاد هشدار میشوند، برطرف کنید.
برای کاربران Visual Studio
برای اینکه با هشدارها مانند خطا رفتار شود، روی نام پروژه خود در پنجره Solution Explorer کلیک راست کرده و سپس Properties (خواص) را انتخاب کنید:
از پنجره Project (پروژه)، ابتدا مطمئن شوید که فیلد Configuration (پیکربندی) روی All Configurations (همه پیکربندیها) تنظیم شده است.
سپس برگه C/C++ > General (عمومی) را انتخاب کرده و Treat Warnings As Errors (رفتار با هشدارها مانند خطا) را روی Yes (/WX) (بله) تنظیم کنید.
برای کاربران Code::Blocks
از منوی Settings > Compiler > Other compiler options (سایر گزینههای کامپایلر)، عبارت -Werror را به ناحیه ویرایش متن اضافه کنید:
برای کاربران gcc
گزینهٔ زیر را به خط فرمان خود اضافه کنید:
-Werror
برای کاربران VS Code
در فایل tasks.json، گزینههای زیر را قبل از “${file}”، هر کدام در یک خط، اضافه کنید:
"-Werror",