Valgrind چیست؟ آموزش کشف باگ های حافظه بوسیله Valgrind

0 42
۵/۵ - (۱ امتیاز)

فهرست

Valgrind چیست؟

Valgrind یک ابزار برنامه نویسی برای اشکال زدایی (دیباگینگ) حافظه، تشخیص نشت حافظه و پروفایلینگ است. Valgrind در ابتدا به عنوان یک ابزار اشکال زدایی حافظه رایگان برای لینوکس در x86 طراحی شده بود، اما از آن زمان به یک چارچوب عمومی برای ایجاد ابزارهای تجزیه و تحلیل پویا (Dynamic Analysis) مانند چکرها و پروفایلرها تبدیل شد. نام Valgrind اشاره ای به ورودی اصلی Valhalla از اساطیر نورس (Norse) است.

Valgrind در اصل یک ماشین مجازی است که از تکنیک‌های کامپایل‌سازی به‌موقع (Just-in-Time Compilation) از جمله Dynamic Recompilation استفاده می‌کند. هیچ چیز از برنامه اصلی هرگز مستقیماً روی پردازنده اجرا نمی شود. در عوض، Valgrind ابتدا برنامه را به یک فرم موقت و ساده‌تر به اسم Intermediate Representation یا همان IR ترجمه می‌کند. IR یک فرم مبتنی بر SSA خنثی از پردازنده است. پس از تبدیل، یک ابزار آزاد است تا هر تغییری را که می‌خواهد در IR انجام دهد، قبل از اینکه Valgrind IR را به کد ماشین ترجمه کند و به پردازنده میزبان اجازه دهد تا آن را اجرا کند. Valgrind کدهای باینری را برای اجرا بر روی هاست و CPUهای هدف (یا شبیه سازی شده) با معماری یکسان، دوباره کامپایل می کند. همچنین شامل یک بخش GDB می‌شود تا امکان اشکال‌زدایی برنامه هدف را در حالی که در Valgrind اجرا می‌شود، با “دستورات Monitor” که امکان جستجو در ابزار Valgrind را برای اطلاعات مختلف فراهم می‌کند.

دریافت و نصب Valgrind

Valgrind فقط لینوکسی است. برای نصب این ابزار کافیست به بخش دانلود وب سایت آن سر بزنید. برای نصب والگریند کافیست فایل دانلود شده را از حالت فشرده خارج کنید:

bzip2 -d valgrind-XYZ.tar.bz2
tar -xf valgrind-XYZ.tar

پس از اینکه فایل ها از حالت فشرده خارج شدند، بوسیله دستورات زیر آن را Make و در ادامه نصب کنید:

./configure
make
make install

کشف مشکلات و نشت حافظه (Memory Leak) با Valgrind

نشت حافظه یا Memory Leak یکی از سخت ترین اشکالات برای شناسایی است زیرا تا زمانی که حافظه شما تمام نشده باشد و Call شما با تابع malloc به طور ناگهانی با مشکل مواجه شود، هیچ مشکل ظاهری ایجاد نمی کند. در واقع، وقتی با زبانی مانند C یا C++ کار می‌کنید که Garbage Collection ندارد، تقریباً نیمی از زمان شما ممکن است صرف مدیریت صحیح حافظه شود. و حتی یک اشتباه می تواند پرهزینه باشد اگر برنامه شما به اندازه کافی اجرا شود و بخش مشکل دار کد، اجرا شود.

وقتی کد خود را اجرا می کنید، باید ابزاری را که می خواهید استفاده کنید مشخص کنید. به سادگی اجرای Valgrind لیست فعلی را به شما می دهد. ما عمدتاً بر روی ابزار memcheck برای این آموزش تمرکز خواهیم کرد زیرا اجرای valgrind با ابزار memcheck به ما امکان می دهد میزان استفاده صحیح از حافظه را بررسی کنیم. بدون هیچ استدلال دیگری، Valgrind خلاصه‌ای از فراخوان‌ها به free و malloc را ارائه می‌کند: (توجه داشته باشید که ۲۳۳۰۰۱ شناسه فرآیند در سیستم من است؛ بین اجراها متفاوت است.)

% valgrind --tool=memcheck program_name
...
=۲۳۳۰۰۱ == malloc/free: in use at exit: 0 bytes in 0 blocks.
==۲۳۳۰۰۱ == malloc/free: 1 allocs, 1 frees, 10 bytes allocated.
==۲۳۳۰۰۱ == For a detailed leak analysis,  rerun with: --leak-check=yes

اگر نشت حافظه دارید، تعداد تخصیص‌ها و تعداد آزادها متفاوت خواهد بود (شما نمی‌توانید از یک حافظه رایگان برای آزاد کردن حافظه متعلق به بیش از یک تخصیص استفاده کنید). ما بعداً به خلاصه خطاها باز خواهیم گشت، اما در حال حاضر، توجه داشته باشید که برخی از خطاها ممکن است سرکوب شوند – این به این دلیل است که برخی از خطاها از روال‌های کتابخانه استاندارد است نه کد خودتان.

اگر تعداد تخصیص‌ها با تعداد رایگان‌ها متفاوت است، می‌خواهید برنامه خود را دوباره با گزینه چک کردن نشت دوباره اجرا کنید. با این کار تمام تماس‌هایی که به malloc/new/etc وجود دارد را نشان می‌دهد. برای اهداف نمایشی، من از یک برنامه بسیار ساده استفاده خواهم کرد که آن را در فایل اجرایی به نام “example1” کامپایل خواهم کرد.

#include <stdlib.h>
int main()
{
    char *x = malloc(100); /* or, in C++, "char *x = new char[100] */
    return 0;
}
% valgrind --tool=memcheck --leak-check=yes example1

این منجر به نمایش برخی اطلاعات در مورد برنامه می‌شود که به فهرستی از تماس‌ها به malloc که تماس‌های بعدی رایگان نداشتند، ختم می‌شود:

==۲۱۱۶== ۱۰۰ bytes in 1 blocks are definitely lost in loss record 1 of 1
==۲۱۱۶==    at 0x1B900DD0: malloc (vg_replace_malloc.c:131)
==۲۱۱۶==    by 0x804840F: main (in /home/cprogram/example1)

اگرچه این به ما چیزی را که می‌خواهیم نمی‌گوید – می‌دانیم که نشت حافظه به دلیل تماس با malloc در اصلی بوده است، اما شماره خط را نداریم. مشکل این است که ما با استفاده از گزینه -g از gcc که نمادهای اشکال زدایی را اضافه می کند، کامپایل نکردیم. بنابراین اگر با نمادهای اشکال زدایی دوباره کامپایل کنیم، خروجی مفیدتر زیر را دریافت می کنیم:

==۲۳۳۰== ۱۰۰ bytes in 1 blocks are definitely lost in loss record 1 of 1
==۲۳۳۰==    at 0x1B900DD0: malloc (vg_replace_malloc.c:131)
==۲۳۳۰==    by 0x804840F: main (example1.c:5)

اکنون خط دقیقی را می دانیم که حافظه از دست رفته در آن تخصیص داده شده است. اگر چه هنوز این سوال است که دقیقاً چه زمانی می خواهید آن حافظه را آزاد کنید، حداقل می دانید از کجا شروع کنید. و از آنجایی که برای هر تماس با malloc یا جدید، باید برنامه ای برای مدیریت حافظه داشته باشید، دانستن اینکه حافظه کجا از بین می رود به شما کمک می کند تا بفهمید کجا باید جستجو کنید.

مواقعی وجود خواهد داشت که گزینه –leak-check=yes منجر به نمایش تمام نشت های حافظه به شما نمی شود. برای پیدا کردن مطلقاً هر تماس جفت نشده رایگان یا جدید، باید از گزینه –show-reachable=yes استفاده کنید. خروجی آن تقریباً یکسان است، اما حافظه آزاد نشده بیشتری را نشان می دهد.

پیدا کردن Invalid Pointer بوسیله Valgrind

Valgrind همچنین می تواند استفاده از حافظه پشته نامعتبر را با استفاده از ابزار memcheck بیابد. به عنوان مثال، اگر یک آرایه را با malloc یا new اختصاص دهید و سپس سعی کنید به مکانی در گذشته از انتهای آرایه دسترسی پیدا کنید:

char *x = malloc(10);
x[10] = 'a';

Valgrind آن را تشخیص خواهد داد. به عنوان مثال، اجرای برنامه زیر، example2، از طریق Valgrind

#include <stdlib.h>

int main()
{
    char *x = malloc(10);
    x[10] = 'a';
    return 0;
}

با کمک دستور زیر:

valgrind --tool=memcheck --leak-check=yes example2

منجر به اخطار زیر می شود:

==۹۸۱۴==  Invalid write of size 1
==۹۸۱۴==    at 0x804841E: main (example2.c:6)
==۹۸۱۴==  Address 0x1BA3607A is 0 bytes after a block of size 10 alloc'd
==۹۸۱۴==    at 0x1B900DD0: malloc (vg_replace_malloc.c:131)
==۹۸۱۴==    by 0x804840F: main (example2.c:5)

درباره ما

ترجنس | thregence.ir
آکادمی ترجنس | edu.thregence.ir
دوره‌های آکادمی ترجنس | courses.thregence.ir
اینستاگرام | instagram.com/thregence
تلگرام | t.me/thregence
یوتوب | https://bit.ly/30mGowo
آپارات | aparat.com/thregence

ارسال یک پاسخ