بعد ، ما یک برنامه ساختگی C ، memory.c ایجاد می کنیم و memwatch.h را به خط 3 اضافه می کنیم تا MEMWATCH فعال شود.
علاوه بر این ، دو پرچم زمان کامپایل -DMEMWATCH و -DMW_STDIO نیاز دارند برای جمع آوری دستورات برای هر فایل منبع در برنامه اضافه شود.
# cat memory.c
1 # شامل شود
2 # شامل شود
3 # شامل "memwatch.h"
چهار
5 اصلی (باطل)
6 {
7 کاراکتر * ptr1؛
8 کاراکتر * ptr2؛
9
10 ptr1 = malloc (512) ؛
11 ptr2 = malloc (512) ؛
12
13 ptr2 = ptr1؛
14 رایگان (ptr2)
15 رایگان (ptr1)
16}
کد فوق دو بلوک 512 بایت حافظه را تخصیص می دهد (سطرهای 10 و 11) و سپس نشانگر بلوک اول روی بلوک دوم (خط 13) تنظیم می شود.
در نتیجه ، آدرس بلوک دوم از بین رفته و نشتی از حافظه رخ می دهد.
اکنون فایل memwatch.c را که بخشی از بسته MEMWATCH است ، با کد منبع نمونه (حافظه1.c) کامپایل کنید.
در زیر یک به عنوان مثال makefile برای ساخت حافظه 1. c. memory1 اجرایی است که توسط این makefile ایجاد شده است: دو ناهنجاری مدیریت حافظه را ضبط می کند.
./ حافظه 1 MEMWATCH 2 ناهنجاری را شناسایی کرد
MEMWATCH یک log به نام memwatch.log ایجاد می کند. همانطور که در زیر مشاهده می کنید ، با شروع حافظه برنامه 1 ایجاد می شود.

MEMWATCH به شما می گوید مشکل از کدام خط است. [19659015] در صورت عدم وجود یک اشاره گر از قبل آزاد شده ، این وضعیت را تشخیص می دهد.
همان حافظه کشف نشده.
در قسمت انتهای گزارش آماری از جمله میزان نشت حافظه ، مقدار حافظه استفاده شده و مقدار کل حافظه اختصاص یافته.
در شکل بالا می بینید که خطاهای مدیریت حافظه در خط 15 رخ می دهد که نشانگر وجود حافظه آزاد دو برابر است.
خطای بعدی نشت حافظه 512 بایت است و این حافظه در خط 11 اختصاص یافته است.
2. Valgrind
Valgrind یک ابزار x86 مختص اینتل است که برای ردیابی مستقیم کلیه دسترسی های حافظه و تجزیه و تحلیل جریان داده ، از پردازنده x86 تقلید می کند. برای آزمایش ، اگر اگر آنها با گزینه -g برای قرار دادن جداول عیب یابی اشکال زدایی ترکیب شوند ، کارایی بهتری خواهد داشت.
این برنامه با اجرای برنامه در یک محیط تقلیدی و رهگیری اجرا در نقاط مختلف کار می کند.
این منجر به اشکال بزرگ Valgrind در این است که با سرعت کم کار می کند و در هنگام آزمایش هر چیزی با محدودیت های زمان واقعی ، از کاربرد کمتری برخوردار است.
Valgrind در اکثر توزیع های لینوکس موجود است ، بنابراین می توانید ابزار را فوراً نصب کنید.
# دور در دقیقه -Uvh /tmp/valgrind-3.15.0-11.el7.x86_64.rpm در حال آماده سازی ... ###########################################################################################################################################################################################>>///D>> در حال به روز رسانی / نصب ... 1: valgrind-1: 3.15.0-11.el7 ###################################### 19# ] سپس می توانید valgrind را روی فرایندی که می خواهید از نظر نشت حافظه بررسی کنید ، اجرا کنید.به عنوان مثال ، می خواهم نشتی حافظه را در فرآیند amsHelper بررسی کنم که با گزینه -f اجرا می شود.
Ctrl + را فشار دهید C برای جلوگیری از نظارت
# valgrind amsHelper -f == 30159 == ممچک ، ردیاب خطای حافظه == 30159 == حق چاپ (C) 2002-2017 ، و GNU GPL ، توسط جولیان سوارد و دیگران. == 30159 == با استفاده از Valgrind-3.15.0 و LibVEX ؛ برای اطلاعات حق چاپ با -h دوباره استفاده کنید == 30159 == دستور: amsHelper -f == 30159 == NET-SNMP نسخه 5.7.3 زیر عامل AgentX متصل است ^ C == 30159 == == 30159 == خلاصه HEAP: == 30159 == در حال استفاده در خروجی: 853،777 بایت در 11106 بلوک == 30159 == کل استفاده از انبوه: 21،779 تخصیص ، 10،673 آزاد ، 28،226،706 بایت تخصیص یافته == 30159 == == 30159 == خلاصه نشت: == 30159 == قطعاً از دست رفته است: 73 بایت در 2 بلوک == 30159 == به طور غیرمستقیم گم شد: 0 بایت در 0 بلوک == 30159 == احتمالاً از دست رفته است: 32،341 بایت در 120 بلوک == 30159 == هنوز هم قابل دسترسی است: 821،363 بایت در 10،984 بلوک == 30159 == سرکوب شده: 0 بایت در 0 بلوک == 30159 == برای دیدن جزئیات حافظه درز ، مجدداً با --leak-check = پر کنید == 30159 == == 30159 == برای لیست های خطاهای شناسایی شده و سرکوب شده ، مجدداً با استفاده از: -s == 30159 == خلاصه خطا: 0 خطا از 0 زمینه (سرکوب شده: 0 از 0)برای ذخیره خروجی در یک پرونده ورود به سیستم و جمع آوری اطلاعات دقیق تر در مورد نشت ، از leak-check-full with –log استفاده کنید -file = / path / og / log / file.
Ctrl + C را فشار دهید تا نظارت متوقف شود
# valgrind --leak-check = full --log-file = / tmp / mem-leak-amsHelper.log amsHelper -f Subagent NET-SNMP نسخه 5.7.3 AgentX متصل استاکنون می توانید محتویات /tmp/mem-leak-amsHelper.log را بررسی کنید.
هنگامی که مشکلی را تشخیص داد ، خروجی Valgrind در قالب زیر است: [19659003] == 771 = = 72 بایت در 1 بلوک قطعاً در رکورد از دست دادن 2،251 از 3462 از بین می رود
== 771 == در 0x4C2B975: calloc (vg_replace_malloc.c: 711)
== 771 == توسط 0x6087603: ؟؟؟ (در /usr/lib64/libnss3.so)
== 771 == توسط 0x60876A8: ؟؟؟ (در /usr/lib64/libnss3.so)
== 771 == توسط 0x6087268: ؟؟؟ (در /usr/lib64/libnss3.so)
== 771 == توسط 0x607C11A: ؟؟؟ (در /usr/lib64/libnss3.so)
== 771 == توسط 0x60808C5: ؟؟؟ (در /usr/lib64/libnss3.so)
== 771 == توسط 0x602A269: ؟؟؟ (در /usr/lib64/libnss3.so)
== 771 == توسط 0x602AA80: NSS_InitContext (در /usr/lib64/libnss3.so)
== 771 == توسط 0x550F3BA: rpmInitCrypto (در /usr/lib64/librpmio.so.3.2.2)
== 771 == توسط 0x52CBF8D: rpmReadConfigFiles (در /usr/lib64/librpm.so.3.2.2)
== 771 == توسط 0x473C74: ؟؟؟ (in / usr / sbin / amsHelper)
== 771 == توسط 0x441E24: ؟؟؟ (در / usr / sbin / amsHelper)3. Memleax
یکی از نقص های والگریند این است که شما نمی توانید نشت حافظه را در یک فرآیند موجود بررسی کنید ، و این همان جایی است که memleax در آن وارد می شود.
آستانه پیش فرض انقضا 10 ثانیه است ، اما شما همیشه باید آن را با توجه به سناریوهای خود با استفاده از گزینه -e تنظیم کنید.
می توانید memleax را از مخزن رسمی github
rpm -Uvh بارگیری کنید /tmp/memleax-1.1.1-1.el7.centos.x86_64.rpm خطا: وابستگی های ناموفق: libdwarf.so.0 () (64 بیت) توسط memleax-1.1.1-1.el7.centos.x86_64 مورد نیاز است libunwind-x86_64.so.8 () (64 بیت) توسط memleax-1.1.1-1.el7.centos.x86_64 مورد نیاز است libunwind.so.8 () (64 بیت) توسط memleax-1.1.1-1.el7.centos.x86_64مورد نیاز است ، بنابراین من این rpms مخزن رسمی خود را به صورت دستی کپی کردم ، چون یک شبکه خصوصی است ، نمی توانم از yum یا dnf استفاده کنید.
# rpm -Uvh /tmp/libdwarf-20130207-4.el7.x86_64.rpm در حال آماده سازی ... ###########################################################################################################################################################################################>>///D>> در حال به روز رسانی / نصب ... 1: libdwarf-20130207-4.el7 #########################################################################################################################################################################################################################IIIIIIII، LIBERTURF-20130207-4 # دور در دقیقه -Uvh /tmp/libunwind-1.2-2.el7.x86_64.rpm در حال آماده سازی ... ###########################################################################################################################################################################################>>>>/> درحال آماده سازی ... در حال به روز رسانی / نصب ... 1: libunwind-2: 1.2-2.el7 ##################################### 19# که من هر دو وابستگی را نصب کرده ام ، جلو می روم و rmm memleax را نصب می کنم:# rpm -Uvh /tmp/memleax-1.1.1-1.el7.centos.x86_64.rpm در حال آماده سازی ... ###########################################################################################################################################################################################>>///D>> در حال به روز رسانی / نصب ... 1: memleax-1.1.1-1.el7.centos ####################################################################################################################################### با باطری_۱.۱.۱-۱ #### [100%]بنابراین شما به PID فرایندی که می خواهید ردیابی کنید نیاز دارید.
آیا می توانید PID فرآیند خود را از خروجی ps -ef
2102 1 0 12 بدست آورید: 29؟ 00:00:01 / sbin / amsHelper -f ریشه 45256 1 0 13:13؟ 00:00:00 صبح کمک کننده root 49372 44811 0 13:23 امتیاز / 0 00:00:00 grep amsHاکنون ما نشت حافظه 45256 PID را بررسی می کنیم.
# memleax 45256 هشدار: خط خطایی برای / usr / sbin / amsHelper یافت نشد == شروع فرایند نظارت 45256 ... CallStack [1]: حافظه با 688 بایت منقضی می شود ، backtrace: 0x00007f0bc87010d0 libc-2.17.so calloc () + 0 0x00000000004079d3 ams یاور 0x0000000000409249 ams یاور 0x0000000000407077 ams یاور 0x00000000004a7a60 ams یاور 0x00000000004a8c4c ams یاور 0x00000000004afd90 ams یاور 0x00000000004ac97a ams جدول یاور_کمک کننده () + 2842 0x00000000004afd90 ams یاور 0x00000000004bae09 ams یاور 0x00000000004bb707 ams یاور 0x00000000004bb880 ams یاور 0x00000000004bbca2 ams یاور 0x00000000004e7eb1 ams یاور 0x00000000004e8a3e amsHelper 0x00000000004e98a9 ams یاور 0x00000000004e98fb ams کمک کننده 0x00000000004051b4 ams یاور 0x00007f0bc869d555 libc-2.17.so __libc_start_main () + 245 0x00000000004053e2 ams یاور CallStack [1]: حافظه با 688 بایت ، 2 بار دیگر منقضی می شود CallStack [1]: 3 بار دیگر حافظه با 688 بایت منقضی می شود CallStack [1]: حافظه با 688 بایت ، 4 بار دیگر منقضی می شود CallStack [1]: حافظه با 688 بایت ، 5 بار دیگر منقضی می شود CallStack [2]: حافظه با 15 بایت منقضی می شود ، backtrace: 0x00007f0bc87006b0 libc-2.17.so malloc () + 0 0x00007f0bc8707afa libc-2.17.so __GI ___ strdup () + 26 0x00007f0bc8731141 libc-2.17.so tzset_internal () + 161 0x00007f0bc8731b03 libc-2.17.so __tz_convert () + 99در صورت وجود نشت حافظه در روند درخواست ، می توانید همان نتیجه فوق را بدست آورید.
Ctrl + C را فشار دهید تا نظارت متوقف شود
4. جمع آوری تخلیه هسته
گاهی اوقات این به یک توسعه دهنده کمک می کند: ما می توانیم فرآیند نشت حافظه هسته ای را به اشتراک بگذاریم.
در Red Hat / CentOS ، می توانید تخلیه هسته را با استفاده از abrt و abrt-addon-ccpp جمع آوری کنید
قبل از شروع ، اطمینان حاصل کنید که سیستم شما با ایجاد محدودیت های هسته برای ساخت هسته برنامه پیکربندی شده است:
# ulimit -c نامحدودسپس این بسته های rpm را نصب کنید:
# yum install abrt abrt-addon- ccpp abrt-tuiاطمینان حاصل کنید که قلاب های ccpp نصب شده اند:
# abrt-install-ccpp-hook نصب # abrt-install-ccpp-hook نصب شده است؛ echo $؟؛اطمینان حاصل کنید که این سرویس در حال اجرا است و قلاب ccpp برای گرفتن مخازن اصلی فعال است:
# systemctl abrtd.service را فعال کنید - اکنون # systemctl فعال کردن abrt-ccpp.service - اکنونفعال کردن قلاب ها
# گزارش خودکار abrt فعال استبرای دریافت لیست خرابی ها در خط فرمان ، دستور زیر را وارد کنید:
# abrt -cli listاما از آنجا که خطایی وجود ندارد ، خروجی خالی خواهد بود.
سپس PID را که می خواهید هسته را برای آن تخلیه کنید پیدا کنید ، به عنوان مثال ، آیا برای PID 45256
root 2102 جمع آوری می کنم 1 0 12:29؟ 00:00:01 / sbin / amsHelper -f ریشه 45256 1 0 13:13؟ 00:00:00 صبح کمک کننده root 49372 44811 0 13:23 امتیاز / 0 00:00:00 grep amsHسپس ما باید یک SIGABRT یعنی 6-سیگنال کشتن را به این PID ارسال کنیم تا یک تخلیه هسته ایجاد کند.
# kill -6 45256سپس می توانید لیست تخلیه های موجود را بررسی کنید ، جایی که می توانید ورودی جدید این PID را مشاهده کنید.
این تخلیه شامل تمام اطلاعات مورد نیاز برای تجزیه و تحلیل نشت این فرآیند است.
5. نحوه تشخیص نشت حافظه با استفاده از ابزارهای استاندارد لینوکس
ما در مورد ابزارهای شخص ثالث بحث کردیم که با استفاده از اطلاعات اضافی در کد که می تواند به توسعه دهنده در تجزیه و تحلیل و رفع اشکال کمک کند ، نشت حافظه را تشخیص دهد.
اما اگر نیاز ما باشد فقط مراقب فرآیندی باشید که بدون دلیل حافظه را ذخیره می کند ، سپس ما باید به ابزارهای سیستم مانند sar ، vmstat ، pmap ، meminfo و غیره اعتماد کنیم.
بنابراین بیایید در مورد استفاده از این ابزارها برای شناسایی سناریوی احتمالی نشت حافظه بیاموزیم .
قبل از شروع ، باید با مناطق زیر آشنا باشید.
- نحوه بررسی حافظه واقعی مصرف شده توسط یک فرایند جداگانه
- چه مقدار حافظه برای روند درخواست شما ذخیره شده است
pmap به شما می دهد همانطور که در زیر می بینید ، جزئیات بیشتری از حافظه مصرف شده توسط بخشهای مختلف آدرس پردازش و کتابخانه ها را می گیرد. [19659011] # pmap -X $ (pgrep amsHelper -f)
15046: / sbin / amsHelper -f
آدرس Perm دستگاه افست اندازه Inode Rss Pss ارجاع شده نقشه ناشناس تعویض قفل شده
00400000 r-xp 00000000 fd: 02 7558 1636 1152 1152 1152 0 0 ams کمک کننده
00799000 r - p 00199000 fd: 02 7558 4 4 4 4 4 0 0 amsHelper
0079a000 rw-p 0019a000 fd: 02 7558 52 48 48 48 20 0 0 amsHelper
007a7000 rw-p 00000000 00:00 0 356 48 48 48 48 0 0
01962000 rw-p 00000000 00:00 0 9716 9716 9716 9716 9716 0 0 [heap]
7fd75048b000 r-xp 00000000 fd: 02 3406 524 320 44 320 0 0 0 libfreeblpriv3.so
7fd75050e000 --- p 00083000 fd: 02 3406 2048 0 0 0 0 0 0 libfreeblpriv3.so
7fd75070e000 r - p 00083000 fd: 02 3406 8 8 8 8 8 0 0 libfreeblpriv3.so
7fd750710000 rw-p 00085000 fd: 02 3406 4 4 4 4 4 0 0 libfreeblpriv3.so
7fd750711000 rw-p 00000000 00:00 0 16 16 16 16 16 0 07fd75ba5f000 rw-p 00022000 fd: 02 4011 4 4 4 4 4 0 0 ld-2.17.so
7fd75ba60000 rw-p 00000000 00:00 0 4 4 4 4 4 0 0
7ffdeb75d000 rw-p 00000000 00:00 0 132 32 32 32 32 0 0 [stack]
7ffdeb79a000 r-xp 00000000 00:00 0 8 4 0 4 0 0 0 [vdso]
fffffffffff600000 r-xp 00000000 00:00 0 4 0 0 0 0 0 0 [vsyscall]
====== ===== ======================================= ================================================= ================================================== ================================================== ================================================= =================================================
196632 15896 13896 15896 10384 0 0 KBدر غیر این صورت می توانید با استفاده از smap های فرآیند مربوطه ، همین اطلاعات را با جزئیات بیشتر دریافت کنید.
در اینجا یک اسکریپت کوچک برای جمع آوری حافظه و بدست آوردن کل وجود دارد ، اما می توانید لوله را نیز حذف کنید و برای جزئیات بیشتر دستور را تقسیم کنید
# cat / proc / $ (pgrep amsHelper) / smaps | grep -i pss | awk '{Total + = $ 2} END {print Total / 1024 "MB"} " 14.4092 MBبنابراین می توانید با استفاده از این ابزارها یک cron job تنظیم کنید و یا یک دایمون ایجاد کنید تا به موقع میزان حافظه برنامه شما را کنترل کند تا ببینید آیا حافظه بیش از حد مصرف می کنند یا خیر.
نتیجه گیری
من دستورات ، ابزارها و تکنیک های مختلفی را برای شناسایی و ردیابی نشت حافظه در انواع مختلف برنامه ها مانند برنامه های C ++ C ، برنامه های لینوکس و غیره به اشتراک گذاشته ام.
انتخاب ابزار به نیاز شما بستگی دارد. بسیاری از ابزارهای دیگر مانند YAMD ، حصار الکتریکی ، هسته ddb هسته و غیره وجود دارد که می تواند به شما در رفع نشت حافظه کمک کند.
سرانجام ، امیدوارم مراحل مقاله بررسی و ردیابی نشت حافظه در لینوکس مفید باشد. [19659095]