[Powered by Google Translate] [Valgrind] [مقابله Hardison، دانشگاه هاروارد] این CS50، CS50.TV] برخی از اشکالات در سخت ترین برنامه های C بیا از سوء مدیریت از حافظه است. تعداد زیادی از راه به پیچ تا چیز وجود دارد، از جمله تخصیص مقدار غلط از حافظه، فراموش کردن برای مقداردهی اولیه متغیر، نوشتن قبل یا بعد از پایان یک بافر، و آزاد چند بار حافظه نگه دارید. علائم از تصادفات متناوب محدوده به ارزش های مرموزی رونویسی، اغلب در مکان ها و زمان های دور از خطا اصلی برداشته است. ردیابی مشکل مشاهده بازگشت به ریشه و علت زمینه ای می تواند چالش برانگیز، اما خوشبختانه یک برنامه مفید به نام Valgrind وجود دارد است که می تواند تا حد زیادی به کمک انجام دهد. شما یک برنامه تحت Valgrind را قادر می سازد بررسی گسترده ای از پشته تخصیص حافظه و دسترسی است. وقتی Valgrind تشخیص مشکل، آن را به شما می دهد فوری، اطلاعات مستقیم است که اجازه می دهد تا شما را به آسان تر از پیدا کردن و حل مشکل. Valgrind همچنین گزارش در مورد مسائل حافظه کمتری مرگبار، مانند نشت حافظه، تخصیص حافظه پشته، و فراموش کردن این برنامه رایگان است. مثل کامپایلر، صدای جرنگ جرنگ، در دیباگر ما، GDB، Valgrind نرم افزار رایگان است، و آن را بر روی دستگاه نصب شده است. Valgrind قابل اجرا بر روی اجرایی باینری، شما نیست. ج. ساعت فایل های کد منبع، بنابراین مطمئن شوید که شما را وارد یک کپی تا به تاریخ برنامه شما با استفاده از صدای جرنگ جرنگ. پس از آن، در حال اجرا برنامه خود را در زیر Valgrind می تواند به عنوان ساده به به عنوان پیشوند دستور برنامه استاندارد با Valgrind کلمه، که شروع می شود تا Valgrind اجرا می شود این برنامه در داخل آن است. هنگام شروع، Valgrind می کند برخی از پیچیده jiggering به پیکربندی اجرایی برای چک حافظه، پس از آن می توانید کمی به بالا و در حال اجرا کنند. این برنامه خواهد شد و سپس به طور معمول اجرا می شود آن را بسیار آهسته تر، و زمانی که آن را پس از اتمام، Valgrind خلاصه ای از استفاده از حافظه خود را چاپ کنید. اگر همه به خوبی می رود، آن را به چیزی شبیه به این: در این مورد، / clean_program مسیر به این برنامه من می خواهم برای اجرا است. و در حالی که این یکی هیچ استدلال را ندارد، اگر آن را به من می خواهم فقط آنها را به رویه در پایان از دستور به طور معمول. پاک کردن برنامه فقط یک برنامه کمی احمقانه من ایجاد شده است که بر روی پشته تخصیص فضا برای یک بلوک از نوع داده int، قرار دادن برخی از ارزش ها در داخل آنها، آزاد و کل بلوک. این همان چیزی است که شما در حال عکسبرداری برای، بدون خطا و بدون نشت. یکی دیگر از متریک مهم تعداد کل بایت اختصاص داده است. بسته به نوع برنامه، اگر اعتبارات خود را در مگابایت یا بالاتر هستند، شما احتمالا در انجام کاری اشتباه است. آیا شما بی ارزش ذخیره تکراری؟ آیا شما با استفاده از پشته برای ذخیره سازی، که از آن بهتر خواهد بود به استفاده از پشته؟ بنابراین، خطاهای حافظه می تواند واقعا بد است. تر آشکار باعث سقوط های دیدنی و جذاب، اما حتی پس از آن هنوز هم می تواند با دقت اشاره کردن آنچه که دقیقا به تصادف منجر شده است. بیشتر خائنانه، یک برنامه با خطای حافظه هنوز هم می توانید به پاک کامپایل و هنوز هم می تواند به درستی کار کند به نظر می رسد دلیل این که شما موفق به دریافت خوش شانس بیشتر از زمان. پس از چندین مورد "نتایج موفقیت آمیز،" شما فقط ممکن است که یک تصادف اتفاق از کامپیوتر فکر می کنم، اما کامپیوتر هرگز اشتباه است. در حال اجرا Valgrind می تواند به شما کمک کند تا پیگیری علت خطاهای حافظه قابل مشاهده و همچنین پیدا کردن کمین اشتباهات شما حتی هنوز نمی دانند در مورد. هر بار Valgrind تشخیص مشکل، آن را چاپ اطلاعات در مورد آنچه در آن مشاهده می باشد. هر یک از آیتم نسبتا مختصر و مفید - خط منبع آموزش متخلف، چه مسئله این است که، و اطلاعات کمی در مورد حافظه درگیر - اما اغلب این اطلاعات به اندازه کافی برای هدایت توجه خود را به جای حق. در اینجا یک مثال از Valgrind در حال اجرا در یک برنامه حشره دار که آیا به عنوان خوانده شده نامعتبر است و از حافظه پشته است. ما می بینیم که هیچ خطا یا هشدار در تدوین. آه، آه، خلاصه خطا می گوید که دو اشتباه وجود دارد - دو بار خوانده شده نامعتبر است از اندازه 4 - بایت، این است که. هر دو بد می خواند رخ داده در تابع اصلی invalid_read.c، برای اولین بار در خط 16 و دوم در خط 19. بیایید نگاهی به کد. به نظر می رسد مثل اولین تماس به printf تلاش می کند به خواندن یک بین المللی گذشته در پایان از بلوک حافظه ما. اگر ما به عقب نگاه در خروجی Valgrind، ما می بینیم که Valgrind به ما گفت که دقیقا. آدرس ما در حال تلاش برای خواندن شروع می شود 0 بایت گذشته پایان بلوک اندازه 16 بایت - چهار 32 بیتی نوع داده int است که ما اختصاص داده شده است. این است که، آدرس ما در تلاش بودند به خواندن شروع می شود درست در پایان بلوک، همانگونه که در تماس printf بد ما را ببینید. در حال حاضر، نامعتبر خوانده شده ممکن است به نظر می رسد مانند که از یک معامله بزرگ، اما اگر شما با استفاده از این داده ها برای کنترل جریان برنامه های خود را - به عنوان مثال، به عنوان بخشی از یک اگر بیانیه و یا حلقه - پس از آن همه چیز سکوت می تواند بد. سازمان دیده بان چگونه می توانم این برنامه invalid_read اجرا و هیچ چیز عادی اتفاق می افتد. ترسناک، متعجب؟ در حال حاضر، اجازه دهید نگاهی به انواع برخی از اشتباهات است که شما ممکن است در کد شما روبرو می شوند، و خواهیم دید که چقدر Valgrind آنها را تشخیص. ما فقط دیدم یک نمونه از invalid_read، بنابراین در حال حاضر را بررسی کنید invalid_write به شما اجازه می دهد تا. باز هم، هیچ خطا یا هشدار در تدوین است. خوب، Valgrind می گوید که دو خطا در این برنامه وجود دارد - و invalid_write و invalid_read. بیایید از این کد. به نظر می رسد مثل ما رو به عنوان مثال کلاسیک strlen به علاوه یک اشکال است. کد می کند بایت اضافی از فضا malloc نیست برای کاراکتر / 0، بنابراین، هنگامی که STR کپی رفت و آن را در ssubstrlen نوشتن "cs50 سنگ!" 1 بایت گذشته پایان بلوک ما نوشت. invalid_read می آید وقتی که ما را به تماس ما را به printf است. Printf به پایان می رسد تا خواندن حافظه نامعتبر است هنگامی که آن را می خواند / 0 از شخصیت ها به عنوان آن را در انتهای این رشته E به نظر می رسد آن را چاپ است. اما هیچ یک از این فرار Valgrind. ما می بینیم که در آن گرفتار invalid_write به عنوان بخشی از نسخه خ در خط 11 از اصلی و invalid_read بخشی از printf است. سنگ در Valgrind. باز هم، این ممکن است به نظر می رسد مانند یک معامله بزرگ است. ما می توانید این برنامه را بارها و بارها اجرا در خارج از Valgrind و هیچ نشانه ای خطا نیست. با این حال، اجازه دهید نگاهی به تنوع کمی از این برای دیدن چه کارهایی می توانید واقعا بد است. بنابراین، داده، ما در حال سوء استفاده از چیزهایی بیشتر از یک بیت در این کد است. ما فقط اختصاص فضا بر روی پشته دو رشته طول cs50 سنگ، در این زمان، به خاطر سپردن / 0 کاراکتر است. اما پس از آن ما در یک رشته فوق العاده را به بلوک حافظه پرتاب که S است با اشاره به. چه اثر است که در بلوک حافظه است که T برای نقاط مورد؟ خوب، اگر T به حافظه که فقط در مجاورت S، فقط پس از آن، پس از آن ما ممکن است بیش از بخشی از T. نوشته شده است اجازه اجرای این کد. نگاهی به آنچه اتفاق افتاده است. رشته ما در بلوک پشته ما هر دو ذخیره می شود به نظر می رسد که چاپ درستی است. هیچ چیز اشتباه به نظر می رسد در همه. با این حال، اجازه دهید به عقب برویم به کد ما و اظهار نظر از خط که در آن ما کپی cs50 سنگ به دومین بلوک حافظه، با اشاره به توسط T. در حال حاضر، هنگامی که ما برای اجرای این کد باید تنها محتویات اولین بلوک حافظه نسخه قابل چاپ کردن را ببینید. اوه، حتی اگر ما STR نسخه هر کاراکتر را به بلوک پشته دوم، با اشاره به توسط T. دریافت نسخه قابل چاپ کردن. در واقع، رشته ما به بلوک اول ما پر شده تصرف بلوک اول و به بلوک دوم، همه چیز به نظر می رسد طبیعی است. Valgrind، هر چند، به ما می گوید داستان واقعی است. وجود دارد بروید. همه از کسانی که نامعتبر خواند و می نویسد. بیایید نگاهی به یک نمونه از نوع دیگری از خطا. در اینجا ما چیزی به جای تاسف است. فضای بین المللی بر روی پشته و ما با شتاب، P - - برای اشاره به آن فضا و یک اشاره گر از نوع int مقداردهی اولیه. با این حال، در حالی که اشاره گر ما است مقداردهی اولیه، داده هایی را که از آن با اشاره به در فقط به هر آشغال است که در آن بخشی از پشته. بنابراین، هنگامی که داده ها یه بار به اعضای هیات من، ما از لحاظ فنی من، مقداردهی اولیه اما ما این کار را با استفاده از داده های ناخواسته. فراخوان به ادعا، که یک ماکرو اشکال زدایی مفید است تعریف شده در درستی به نام ادعا کتابخانه، اراده سقط جنین برنامه اگر شرایط آزمون خود را با شکست مواجه شده است. این است که، اگر من 0 است. با توجه به آنچه در فضای پشته بود، با اشاره به توسط P این برنامه گاهی اوقات ممکن است کار کند و در زمان های دیگر شکست. اگر کار می کند، ما فقط خوش شانس. کامپایلر این خطا نمی رسد، اما مطمئن شوید Valgrind. خطا ناشی از استفاده ما از اطلاعات آشغال که ما می بینیم. هنگامی که شما تخصیص حافظه پشته اما آن را deallocate یا رایگان از آن، است که به نام نشت. کوچک، کوتاه مدت برنامه ای است که اجرا می شود و بلافاصله پس از خروج، نشت نسبتا بی ضرر هستند، اما برای یک پروژه از اندازه بزرگتر و / یا طول عمر، حتی یک سوراخ کوچک می تواند به چیزی بزرگ ترکیب. برای CS50، ما از شما انتظار مراقبت از آزاد همه از حافظه پشته که به شما اختصاص، از آنجایی که ما می خواهیم شما را به ایجاد مهارت های لازم برای روند کتابچه راهنمای کاربر به درستی رسیدگی مورد نیاز توسط C. برای انجام این کار، برنامه خود را باید دقیق یک به یک مکاتبات بین malloc و تماس رایگان. خوشبختانه، Valgrind می تواند شما را با نشت حافظه کمک کند بیش از حد. در اینجا است که یک برنامه چکه کن به نام leak.c که اختصاص فضا را بر روی پشته، می نویسد: به آن است، اما این برنامه رایگان نیست. آن را کامپایل ما با ایجاد و اجرای آن را تحت Valgrind، و ما می بینیم که، در حالی که ما هیچ خطاهای حافظه، ما یک نشت. 16 بایت قطعا از دست رفته وجود دارد، به این معنی که اشاره گر به آن حافظه در محدوده زمانی بود که این برنامه خارج است. در حال حاضر، Valgrind به ما یک تن اطلاعات در مورد نشت، اما اگر این یادداشت کوچک را دنبال می کنیم آن را می دهد که به سمت پایین از گزارش خود به نمایش مجدد فیلم - نشت بررسی کامل برای دیدن جزئیات کامل از حافظه به بیرون درز، خواهیم اطلاعات بیشتری دریافت کنید. در حال حاضر، در خلاصه پشته، Valgrind به ما می گوید که در آن حافظه است که از دست داده بود در ابتدا اختصاص داده شد. همانطور که می دانید از به دنبال در کد منبع، Valgrind به ما اطلاع داده است که ما به بیرون درز حافظه اختصاص داده شده با یک تماس به malloc در خط 8 از leak.c در تابع اصلی. زیبا بسیار خوب است. Valgrind طبقه بندی نشت با استفاده از این شرایط: قطعا از دست داده است - این است که پشته اختصاص داده حافظه که به این برنامه دیگر دارای یک اشاره گر است. Valgrind می داند که شما یک بار تا به حال اشاره گر، ولی پس از پیگیری از آن را از دست داده است. این حافظه است که قطعا به بیرون درز است. به طور غیر مستقیم از دست داده است - این است که پشته اختصاص داده حافظه که اشاره گر به آن نیز از دست داده است. به عنوان مثال، اگر شما از دست داده اشاره گر خود را به اولین گره لیست پیوندی، سپس خود گره اول خواهد بود قطعا از دست داده است، در حالی که هر گره پس از آن می توان به طور غیر مستقیم از دست داده است. احتمالا از دست داده است - این است که پشته اختصاص داده حافظه که به Valgrind نمی تواند مطمئن باشد که آیا یک اشاره گر وجود دارد یا نه. هنوز هم در دسترس heap از حافظه اختصاص داده شده است که این برنامه هنوز هم دارای یک اشاره گر در خروج، که به طور معمول این بدان معنی است که جهانی متغیر به آن است. برای بررسی این نشت، شما همچنین باید این گزینه را به - هنوز قابل دسترسی = بله در نیایش خود را از Valgrind. این موارد مختلف ممکن است استراتژی های مختلفی را برای تمیز کردن آنها نیاز به، اما نشت باید حذف شود. متاسفانه، رفع نشت می تواند سخت به انجام. از آنجا که تماس های نادرست به رایگان می توانید منفجر کردن برنامه شما. برای مثال، اگر ما در invalid_free.c نگاه، ما می بینیم به عنوان مثال از deallocation حافظه بد. آنچه که باید تماس تنها به آزاد کل بلوک از حافظه اشاره کرد به توسط int_block، به جای تبدیل شدن به یک تلاش برای آزاد اندازه هر بخش INT- از حافظه جداگانه است. این catastrophically با شکست مواجه خواهد شد. بوم! چه خطا است. این است که قطعا خوب نیست. اگر شما با این نوع از خطا گیر کرده است، هر چند، و شما نمی دانید که به کجا نگاه کنند. سقوط در بهترین دوست شما. شما آن را حدس زده - Valgrind. Valgrind، مثل همیشه، می داند که دقیقا همان چیزی است که تا. تعداد alloc و آزاد با هم مطابقت ندارند. ما باید 1 alloc و 4 آزاد است. و Valgrind همچنین به ما می گوید که در آن برای اولین بار بد رایگان - یکی از که باعث blowup - در حال آمدن است - خط 16. همانطور که می بینید، تماس های بد را به آزاد واقعا بد است، بنابراین توصیه می کنیم اجازه نشت برنامه خود را در حالی که شما در حال کار بر روی قابلیت صحیح است. شروع به دنبال نشت تنها پس از برنامه های خود را در حال کار مناسب، بدون هیچ گونه اشتباهات دیگر. و این همه ایم برای این فیلم کردم. در حال حاضر آنچه از شما انتظار دارند؟ برو اجرا Valgrind در برنامه های خود را در حال حاضر. نام من مقابله Hardison است. این CS50 است. [CS50.TV]