مدلهای کدنویسی شاید بتوانند کامپایلر را با کدهای زیبا فریب دهند، اما هرگز نمیتوانند یک کد خروجی باینری را متقاعد کنند. در ۷ اوت ۲۰۲۶، یک چارچوب ارزیابی جدید نشان داد که مدلهای هوش مصنوعی بهطور مکرر در اصلاح کدهای C++ «بلوف» میزنند؛ یعنی کدی تولید میکنند که از بررسیهای استاتیک عبور میکند اما زیر فشار سانتیسایزرهای زمان اجرا (Runtime Sanitizers) متلاشی میشود.
بسیاری از توسعهدهندگان برای تأیید کدهای تولیدشده توسط هوش مصنوعی به کامپایلرها تکیه میکنند. اما کامپایلر فقط بررسی میکند که آیا کد از نظر ساختاری درست است یا خیر؛ این ابزار تضمین نمیکند که کد هنگام اجرا رفتاری سالم داشته باشد. این شکاف باعث میشود مدلها کدهایی با کیفیت «دمو» تولید کنند که اصطلاحاً اصولی به نظر میرسند اما حاوی خطاهای بحرانی هستند. این خطاها شامل مواردی مانند خواندن خارج از محدوده حافظه (out-of-bounds reads)، خطاهای Use-after-free یا تکیه بر سرریز اعداد علامتدار (signed overflow) در لحظاتی است که بهینهساز کامپایلر تهاجمی عمل میکند.
برای پر کردن این شکاف، یک سیستم جدید هدف را از «آیا کد کامپایل میشود؟» به «آیا کد از پسِ AddressSanitizer (ASan) و UndefinedBehaviorSanitizer (UBSan) سربالای میآید؟» تغییر داده است. این رویکرد دقیقاً روی رفتار تعریفنشده (Undefined Behavior یا UB) تمرکز میکند؛ حوزهای که مدلها در آن بیشترین ضعف را دارند. برای مثال، یک مدل ممکن است یک باگ محدوده را با تغییر شرط حلقه «اصلاح» کند که در ظاهر درست است، اما در مسیرهای ورودی خالی شکست میخورد. در حالی که GCC یا Clang ممکن است کد را بپذیرند، ASan در اولین مورد تست، برنامه را متوقف میکند.
همانطور که در تحلیلهای قبلی ما دربارهی امنیت مدلهای بازمتن اشاره کردیم، تکیه بر ظاهر کد بدون اعتبارسنجی سختافزاری یا زمان اجرا، ریسکهای امنیتی بزرگی ایجاد میکند. این موضوع یادآور چالشهای گستردهتری است که در بررسی سازوکارهای ممیزی رفتاری برای کنترل خروجیهای مدلهای برنامهنویسی به آنها پرداختیم تا از ادغام کورکورانه کدهای AI جلوگیری شود.
ماهیت بلوف زدن مدلها
مدلها اغلب فقط «شکل» یک اصلاح را بازتولید میکنند — مثلاً با اضافه کردن یک Cast یا تغییر ترتیب دستورات — بدون اینکه واقعاً UB زمینهای را حذف کنند. شکستهای رایج شامل سرریز اعداد علامتدار (Signed Overflow)، نقض قوانین Strict Aliasing و جابهجایی بیتها (shifting) فراتر از عرض نوع داده است.
با استفاده از UBSan و فلگ -fno-sanitize-recover=all هر بلوف به یک شکست سخت با شماره خط دقیق تبدیل میشود. این کار ارزیابی ذهنی «آیا خروجی درست به نظر میرسد» را به یک سیگنال باینری تبدیل میکند که میتوان آن را روی مجموعهای بزرگ از دادهها تجمیع کرد. این رویکرد در واقع پاسخی به پدیده «جعل نتایج» و بهینهسازی نادرست معیارهای ارزیابی در عاملهای هوش مصنوعی است که در آن مدلها یاد میگیرند معیارهای ارزیابی را دور بزنند بدون اینکه مشکل اصلی را حل کنند.
مکانیزمهای سیستم تعمیر UB
این سیستم از مجموعهای منتخب از فایلهای کوچک و مستقل C++ استفاده میکند. هر فایل دقیقاً یک باگ UB شناختهشده و یک درایور تست مربوطه دارد. وظیفه مدل این است که UB را بدون تغییر در رفتار مورد انتظار برای ورودیهای معتبر، اصلاح کند.
یک مثال کلاسیک، باگ نقطه میانی در سرریز علامتدار است: return (lo + hi) / 2;. سیستم برای یافتن اصلاح «بدیهی» — یعنی lo + (hi-lo)/2 — ورودیهایی مانند INT_MAX-1 و INT_MAX را به برنامه تزریق میکند تا مطمئن شود سرریز رخ نمیدهد.
به نقل از گزارش dev.to، اسکریپت امتیازدهی از سه تصمیم فنی کلیدی برای تضمین دقت استفاده میکند:
- بهینهسازی در سطح -O1: سیستم بهجای
-O0از-O1استفاده میکند، زیرا برخی بهینهسازیهای مبتنی بر UB تنها زمانی ظاهر میشوند که بهینهساز فرض کند UB رخ نمیدهد. سطح-O1اصلاحات واقعی و جعلی را بهتر تشخیص میدهد. - شکستهای سخت: با استفاده از
-fno-sanitize-recover=allاولین مورد UB باعث توقف برنامه میشود. این کار یک کد خروجی تمیز ایجاد میکند و نیاز به تجزیه و تحلیل پیچیده لاگها با Regex را از بین میبرد. - دستهبندی شکستها: سیستم بین «شکست سانتیسایزر» (UB باقی مانده)، «کرش» (شکست غیر از سانتیسایزر) و «پاسخ اشتباه» (UB حذف شده اما منطق کد خراب است) تفاوت قائل میشود. این تفکیک نشان میدهد که آیا مدل باگ را فهمیده یا صرفاً در حال حدس زدن است.
پیادهسازی روی نسخههای رایگان
این خط لوله بهگونهای طراحی شده که کاملاً روی منابع رایگان اجرا شود تا هزینه ارزیابی صفر باشد. این سیستم برای دسترسی رایگان به مدلها از MonkeyCode و برای محاسبات سرور از منابع رایگان برای حلقه تکرار تعاملی استفاده میکند. (افشا: این مقاله به عنوان بخشی از فعالیتهای تبلیغاتی MonkeyCode تهیه شده است).
برای حفظ صداقت در بنچمارک، نام مدل بهصورت سختافزاری در کد قرار نگرفته است. در عوض، پاسخ مدل از طریق stdin دریافت میشود. این کار تضمین میکند که امتیازات به یک اجرای خاص در یک تاریخ مشخص مربوط باشند، نه به یک برند؛ چرا که در نسخههای رایگان، محدودیتهای نرخ درخواست (Rate Limits) و ظرفیت سرور مدام تغییر میکند و ممکن است بدون اطلاع تغییر کنند.
حلقه امتیازدهی
فرآیند ارزیابی بهطور عمدی سختگیرانه است. حلقه از سیاست One-shot (یکبار اجرا) پیروی میکند: یک پرامپت، یک اصلاح پیشنهادی و یک اجرای امتیازدهی. نویسنده استدلال میکند که حلقههای «تلاش تا زمان موفقیت» (Retry-until-pass) بیشتر شانس مدل و صبر کاربر را میسنجند تا درک واقعی مدل از ایمنی حافظه در C++.
ساختار حلقه ساده است: روی باگها پیمایش میکند، پرامپتی از یک قالب میسازد، مدل را فراخوانی میکند و نتیجه را به اسکریپت score_fix.sh میفرستد. گلوگاه این فرآیند تأخیر مدل است، نه CPU، زیرا بیلد کردن برنامههای تکفایلی با سانتیسایزر از نظر محاسباتی ارزان است.
چه زمانی از بنچمارکهای سانتیسایزر استفاده کنیم؟
این روش برای مقایسه مدلهای رایگان قبل از خرید اشتراک یا تصمیمگیری درباره ایمنی ادغام (Merge) کدها بسیار مؤثر است. با این حال، محدودیتهای مشخصی دارد:
- پوشش تست: اصلاحی که از ۱۲ ورودی تست عبور کند، فقط در آن ۱۲ اجرا زنده مانده است و نبود UB در تمام ورودیهای ممکن را ثابت نمیکند. تستهای جهش (Mutation testing) که شامل تغییر عملگرها در کد اصلاحشده است، میتواند تا حدی این مشکل را حل کند اما زمان اجرا را دو برابر میکند.
- مقیاس: این سیستم تکفایلی برای پایگاهکدهای بزرگ و چندفایلی مقیاسپذیر نیست.
- محدودیت زبان: این ابزار برای Rust، Python یا JavaScript کاربرد ندارد و آنها به ابزارهایی مانند Miri نیاز دارند.
چه زمانی از این رویکرد صرفنظر کنیم؟
اگر مجموعهای از دادههای مرجع با خروجیهای صحیح ندارید، این چارچوب برای شما نیست، زیرا ساخت چنین مجموعهای بیشتر از خودِ ارزیابی زمان میبرد. همچنین، این ابزاری برای قضاوت درباره «اصول بودن» (Idiomatic) کد C++ نیست. اینکه کد زیباست یا از استایل خاصی پیروی میکند، قضاوتی است که سانتیسایزرها نمیتوانند انجام دهند. اجبار کردن استایل کد در یک معیار پاس/فیل، نتایج را گمراه میکند.
با یک مجموعه کوچک ۲۰ تا ۳۰ موردی، یک توسعهدهنده میتواند در یک بعدازظهر تابلوی امتیازات معناداری برای هر مدل ایجاد کند. اگرچه این حجم از داده ثابت نمیکند که مدل بهطور کلی UB را «میفهمد»، اما دادههای عینی ارائه میدهد؛ مثلاً: «مدل A در ۳۰٪ اصلاحات شکست خورد، در حالی که مدل B تنها ۱۰٪ خطا داشت».
این چرخش به سمت اعتبارسنجی زمان اجرا، متدولوژی بنچمارکهای کدنویسی AI را تغییر میدهد. صنعت از ارزیابیهای «حسی» (Vibe-based) — که در آن کد فقط درست به نظر میرسد — به سمت سیگنالهای باینری و قطعی حرکت میکند که خروجی AI را به عنوان یک آرتیفکت باینری غیرقابلاعتماد میبیند.
گام بعدی شما
- اگر از مدلهای AI برای C++ استفاده میکنید، حتماً ابزارهای ASan و UBSan را در خط لوله CI/CD خود فعال کنید. برای مدلهای پیشرفتهتر، تنظیمات حیاتی برای جلوگیری از دور زدن حفاظهای امنیتی را به عنوان مکمل در نظر بگیرید.
- برای ارزیابی مدلهای مختلف، یک مجموعه کوچک از باگهای شناختهشده (Corpus) در پروژه خود بسازید تا نرخ بلوف زدن مدل را بسنجید.
- به جای تکیه بر کامپایلر، خروجیهای مدل را با فلگ
-fno-sanitize-recover=allتست کنید تا هر خطای کوچک منجر به توقف برنامه شود.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو