| GCOV(1) | GNU | GCOV(1) |
نام (NAME)
or1k-elf-gcov - ابزار بررسی و تحلیل پوشش کد برای برنامههای معماری OpenRISC
خلاصه دستور (SYNOPSIS)
gcov [-v|--version] [-h|--help]
[-a|--all-blocks]
[-b|--branch-probabilities]
[-c|--branch-counts]
[-g|--conditions]
[-e|--prime-paths]
[--prime-paths-lines[=type]]
[--prime-paths-source[=type]]
[-d|--display-progress]
[-f|--function-summaries]
[--include regex]
[--exclude regex]
[-j|--json-format]
[-H|--human-readable]
[-k|--use-colors]
[-l|--long-file-names]
[-m|--demangled-names]
[-M|--filter-on-demangled]
[-n|--no-output]
[-o|--object-directory directory|file]
[-p|--preserve-paths]
[-q|--use-hotness-colors]
[-r|--relative-only]
[-s|--source-prefix directory]
[-t|--stdout]
[-u|--unconditional-branches]
[-x|--hash-filenames]
files
توضیحات (DESCRIPTION)
برنامه gcov یک ابزار سنجش پوشش آزمون کد (Test Coverage) است. از آن همراه با GCC استفاده کنید تا برنامههای خود را تحلیل کرده و کدهای بهینهتر و سریعتری ایجاد نمایید و بخشهای آزمودهنشده برنامه را کشف کنید. میتوانید از gcov به عنوان ابزار پروفایلسازی (Profiling) برای تعیین مؤثرترین بخشها جهت بهینهسازی استفاده کنید. همچنین میتوانید gcov را همراه با ابزار پروفایلسازی دیگر یعنی gprof به کار ببرید تا مشخص شود کدام قسمتهای کد بیشترین زمان پردازشی را مصرف میکنند.
ابزارهای پروفایلسازی به شما در تحلیل کارایی کد کمک میکنند. با استفاده از یک ابزار پروفایلسازی مانند gcov یا gprof میتوانید آمارهای اولیهای از کارایی برنامه به دست آورید؛ از جمله:
- هر خط از کد چند بار اجرا میشود
- کدام خطوط کد واقعاً اجرا شدهاند
- هر بخش از کد چه مقدار زمان پردازشی مصرف میکند
هنگامی که این موارد را درباره نحوه اجرای کد کامپایلشده دانستید، میتوانید تکتک ماژولها را بررسی کنید تا ببینید کدام ماژولها باید بهینهسازی شوند. gcov به شما در یافتن نقاط مناسب برای بهینهسازی کمک میکند.
توسعهدهندگان نرمافزار همچنین از سنجش پوشش آزمون همراه با مجموعههای آزمون (Testsuites) استفاده میکنند تا مطمئن شوند نرمافزار برای انتشار نهایی به اندازه کافی آماده است. مجموعههای آزمون بررسی میکنند که آیا برنامه طبق انتظار کار میکند یا خیر؛ برنامه سنجش پوشش نیز بررسی میکند چه مقدار از کد توسط مجموعه آزمون پوشش داده شده است. بدین ترتیب توسعهدهندگان میتوانند مشخص کنند چه سناریوهای آزمایشی جدیدی باید به مجموعه آزمون افزوده شود تا آزمون بهتر و محصول نهایی باکیفیتتری تولید گردد.
اگر قصد استفاده از gcov را دارید، بهتر است کد خود را بدون بهینهسازی کامپایل کنید؛ زیرا بهینهسازی با ادغام چند خط کد در یک تابع، ممکن است اطلاعات مورد نیاز برای یافتن «نقاط داغ» (Hot Spots) که زمان زیادی مصرف میکنند را در اختیارتان قرار ندهد. همچنین از آنجا که gcov آمارها را بر اساس هر خط (در پایینترین وضوح) جمعآوری میکند، بیشترین بازدهی را با سبک برنامهنویسیای دارد که در هر خط فقط یک دستور قرار میگیرد. اگر از ماکروهای پیچیدهای استفاده کنید که به حلقهها یا ساختارهای کنترلی دیگر گسترش مییابند، آمارها کارایی کمتری خواهند داشت و فقط برای خطی که فراخوانی ماکرو در آن رخ داده گزارش میشوند. اگر ماکروهای پیچیده شما مانند تابع رفتار میکنند، میتوانید برای رفع این مشکل آنها را با توابع درونخطی (Inline Functions) جایگزین کنید.
ابزار gcov یک فایل گزارش با نام sourcefile.gcov ایجاد میکند که نشان میدهد هر خط از فایل منبع sourcefile.c چند بار اجرا شده است. میتوانید این فایلهای گزارش را همراه با gprof برای تنظیم دقیق کارایی برنامههای خود به کار ببرید. gprof اطلاعات زمانبندی را ارائه میدهد که میتوانید در کنار اطلاعات بهدستآمده از gcov استفاده کنید.
ابزار gcov فقط روی کدهای کامپایلشده با GCC کار میکند و با هیچ مکانیزم پروفایلسازی یا سنجش پوشش دیگری سازگار نیست.
گزینهها (OPTIONS)
- -a
- --all-blocks
- شمارش اجرای هر بلوک پایه (Basic Block) را به صورت جداگانه ثبت میکند. به طور معمول gcov شمارش اجرا را فقط برای بلوکهای اصلی هر خط نمایش میدهد. با این گزینه میتوانید بررسی کنید که آیا بلوکهایی درون یک خط وجود دارند که اجرا نشده باشند یا خیر.
- -b
- --branch-probabilities
- تواتر شاخهها (Branches) را در فایل خروجی و خلاصه شاخهها را در خروجی استاندارد مینویسد. این گزینه به شما اجازه میدهد ببینید هر شاخه در برنامه چند بار انتخاب شده است. شاخههای نامشروط نشان داده نخواهند شد، مگر اینکه گزینه -u داده شده باشد.
- -c
- --branch-counts
- تواتر شاخهها را به جای درصد شاخههای طیشده، به صورت تعداد شاخههای طیشده مینویسد.
- -g
- --conditions
- پوشش شرطها را در فایل خروجی و خلاصه اطلاعات شرطها را در خروجی استاندارد مینویسد. این گزینه به شما امکان میدهد بررسی کنید که آیا شرطهای برنامه حداقل یک بار تأثیر مستقلی بر نتیجه عبارت بولی داشتهاند یا خیر (پوشش شرط/تصمیم اصلاحشده یا MC/DC). این گزینه نیازمند کامپایل کد منبع با گزینه -fcondition-coverage است.
- -e
- --prime-paths
- پوشش مسیرها را در فایل خروجی و خلاصه اطلاعات مسیرها را در خروجی استاندارد مینویسد. این گزینه به شما اجازه میدهد ببینید چند مسیر اولیه (Prime Paths) حداقل یک بار طی شدهاند. یک مسیر دنبالهای از بلوکهای پایه است. یک مسیر ساده است اگر بلوک تکراری نداشته باشد (بدون حلقه) به جز احتمالاً بلوک اول و آخر، و مسیر اولیه است اگر مسیری ساده با حداکثر طول باشد. در خروجی عادی، این گزینه فقط تعداد مسیرهای پوششدادهشده را شامل میشود. برای اطلاعات دقیقتر درباره مسیرها میتوانید از --prime-paths-lines یا --prime-paths-source استفاده کنید. با --json-format تمامی جزئیات مسیرها در خروجی گنجانده میشوند. این گزینه نیازمند کامپایل کد منبع با -fpath-coverage است.
- --prime-paths-lines [=type]
- پوشش مسیر را در فایل خروجی و خلاصه اطلاعات مسیر را در خروجی استاندارد مینویسد. این گزینه نشان میدهد چه تعداد مسیر اولیه حداقل یک بار طی شدهاند و گزارشی فشرده از مسیرهای پوششدادهشده یا پوششدادهنشده و نحوه پوشش آنها ارائه میدهد. این حالت برای گزارشگیری خودکار و ردیابی پیشرفت مفید است. مقدار type میتواند حذف شود یا یکی از موارد زیر باشد:
- uncovered - شامل مسیرهای پوششدادهنشده (طینشده). این مقدار پیشفرض است.
- covered - شامل مسیرهای پوششدادهشده (طیشده).
- both - شامل همه مسیرها. معادل استفاده همزمان از covered و uncovered.
این نمونهای از خروجی --prime-paths-lines است:
paths covered 12 of 15 path 2 not covered: lines 8 8(false) 11(true) 11 13(true) 13(true) 14 17 path 3 not covered: lines 8 8(false) 11(true) 11 13(true) 13(false) 16 17 path 4 not covered: lines 8 8(false) 11(true) 11 13(false) 16 17
این بدان معناست که برای پوشش مسیر ۲ باید خطوط ۸، ۱۱، ۱۳، ۱۴ و ۱۷ را اجرا کنید، به طوری که ارزیابی تصمیم در خط ۸ برابر false و تصمیمات در خطوط ۱۱ و ۱۳ برابر "false" باشد.
- --prime-paths-source [=type]
- پوشش مسیر را در فایل خروجی و خلاصه اطلاعات مسیر را در خروجی استاندارد مینویسد. این گزینه نشان میدهد چه تعداد مسیر اولیه حداقل یک بار طی شدهاند و گزارشی دقیق از مسیرهای پوششدادهنشده و نحوه پوشش آنها ارائه میدهد. این حالت برای درک مسیرها و تعامل میان بخشهای برنامه مفید است. مقدار type میتواند حذف شود یا یکی از موارد زیر باشد:
- uncovered - شامل مسیرهای پوششدادهنشده (طینشده). این مقدار پیشفرض است.
- covered - شامل مسیرهای پوششدادهشده (طیشده).
- both - شامل همه مسیرها. معادل استفاده همزمان از covered و uncovered.
این نمونهای از خروجی --prime-paths-source است:
path 10 not covered:
BB 3: 8: for (i = 0; i < 10; i++)
BB 3: 9: total += i;
BB 4: (false) 8: for (i = 0; i < 10; i++)
BB 5: (true) 11: int v = total > 100 ? 1 : 2;
BB 6: 11: int v = total > 100 ? 1 : 2;
BB 8: (false) 13: if (total != 45 && v == 1)
BB 11: 16: printf ("Success\n");
BB 12: 17: return 0;
ستون اول (BB) دنباله بلوکهای پایه است (گزینه -w را ببینید). ستون میانی (true/false) تصمیم اتخاذشده برای آن خط است. ستون سوم شماره خط و ستون چهارم خود خط کد است. این خطوط باید به همین ترتیب اجرا شوند تا مسیر ۱۰ پوشش داده شود.
- -d
- --display-progress
- نمایش میزان پیشرفت در خروجی استاندارد.
- -f
- --function-summaries
- چاپ خلاصه اطلاعات برای هر تابع علاوه بر خلاصه کلی سطح فایل.
- --include regex
- گنجاندن توابعی که با عبارت باقاعده regex تطابق دارند. این گزینه باعث میشود gcov فقط برای توابعی گزارش تهیه کند که با عبارت باقاعده گسترده regex همخوانی دارند. این فلگ میتواند با --exclude ترکیب شود. اگر تابعی هم با include و هم با exclude همخوانی داشته باشد، آخرین مورد اعمال میشود. به طور پیشفرض gcov همه توابع را گزارش میکند، اما اگر --include استفاده شود، فقط توابع منطبق گزارش خواهند شد.
- --exclude regex
- مستثنی کردن توابعی که با عبارت باقاعده regex تطابق دارند. این گزینه باعث میشود gcov از گزارشدهی درباره توابعی که با عبارت باقاعده گسترده regex همخوانی دارند صرفنظر کند. این فلگ میتواند با --include ترکیب شود. اگر تابعی هم با include و هم با exclude همخوانی داشته باشد، آخرین مورد اعمال خواهد شد. به طور پیشفرض gcov همه توابع را گزارش میکند و در صورت استفاده از --exclude توابع منطبق حذف میشوند.
- -h
- --help
- نمایش راهنمای استفاده از gcov (در خروجی استاندارد) و خروج بدون انجام پردازش دیگر.
- -j
- --json-format
- تولید فایل
gcov در قالب
میانی JSON با
قابلیت
پارس آسان
که برای
تولید
نیازی به
دسترسی به
کد منبع
ندارد. فایل
JSON با
الگوریتم gzip
فشرده شده و
دارای
پسوند .gcov.json.gz
خواهد بود.
ساختار این فایل JSON به صورت زیر است:
{ "current_working_directory": "foo/bar", "data_file": "a.out", "format_version": "2", "gcc_version": "11.1.1 20210510" "files": ["$file"] }فیلدهای عنصر ریشه دارای معانی زیر هستند:
- current_working_directory: دایرکتوری کاری که واحد کامپایل در آن کامپایل شده است
- data_file: نام فایل داده (GCDA)
- format_version: نسخه
معنایی
قالب داده
تغییرات در نسخه 2:
- *
- calls: اطلاعات مربوط به فراخوانی توابع اضافه شده است
- *
- gcc_version: نسخه کامپایلر GCC
هر عنصر file به شکل زیر است:
{
"file": "a.c",
"functions": ["$function"],
"lines": ["$line"]
}
فیلدهای عنصر file دارای معانی زیر هستند:
- *
- file_name: نام فایل منبع
هر عنصر function به شکل زیر است:
{
"blocks": 2,
"blocks_executed": 2,
"demangled_name": "foo",
"end_column": 1,
"end_line": 4,
"execution_count": 1,
"name": "foo",
"start_column": 5,
"start_line": 1
}
فیلدهای عنصر function دارای معانی زیر هستند:
- blocks: تعداد بلوکهای موجود در تابع
- blocks_executed: تعداد بلوکهای اجراشده از تابع
- demangled_name: نام نامگشاییشده (Demangled) تابع
- end_column: ستونی در فایل منبع که تابع در آن پایان مییابد
- end_line: خطی در فایل منبع که تابع در آن پایان مییابد
- execution_count: تعداد دفعات اجرای تابع
- name: نام تابع
- start_column: ستونی در فایل منبع که تابع از آنجا شروع میشود
- start_line: خطی در فایل منبع که تابع از آنجا شروع میشود
توجه داشته باشید که شماره خطوط و ستونها از ۱ آغاز میشوند. در پیادهسازی کنونی، start_line و start_column شامل پارامترهای قالب (Template Parameters) و نوع بازگشتی ابتدایی نمیشوند، اما احتمالاً این مورد در آینده برطرف خواهد شد.
هر عنصر line به شکل زیر است:
{
"block_ids": ["$block_id"],
"branches": ["$branch"],
"calls": ["$call"],
"count": 2,
"conditions": ["$condition"],
"line_number": 15,
"unexecuted_block": false,
"function_name": "foo",
}
شاخهها و فراخوانیها فقط با گزینه -b حضور دارند. فیلدهای عنصر line دارای معانی زیر هستند:
- block_ids: شناسههای بلوکهای پایه متعلق به این خط
- count: تعداد دفعات اجرای خط
- line_number: شماره خط
- unexecuted_block: پرچمی که نشان میدهد آیا خط حاوی بلوک اجرانشده است یا خیر (همه دستورات خط اجرا نشدهاند)
- function_name: نام تابعی که این line متعلق به آن است (برای خطی با دستورات درونخطی ممکن است مقداردهی نشود)
هر عنصر branch به شکل زیر است:
{
"count": 11,
"destination_block_id": 17,
"fallthrough": true,
"source_block_id": 13,
"throw": false
}
فیلدهای عنصر branch دارای معانی زیر هستند:
- count: تعداد دفعات اجرای شاخه
- fallthrough: برابر true در صورتی که شاخه از نوع سرریز/عبور مستقیم (Fall-through) باشد
- throw: برابر true در صورتی که شاخه از نوع استثنا (Exceptional) باشد
- isource_block_id: شناسه (ID) بلوک پایهای که این شاخه از آن سرچشمه میگیرد
- destination_block_id: شناسه (ID) بلوک پایهای که این شاخه به آن میپرد
هر عنصر call به شکل زیر است:
{
"destination_block_id": 1,
"returned": 11,
"source_block_id": 13
}
فیلدهای عنصر call دارای معانی زیر هستند:
- returned: تعداد دفعاتی که فراخوانی تابع با موفقیت برگشته است (تعداد فراخوانیها برابر با line::count است)
- isource_block_id: شناسه (ID) بلوک پایهای که این فراخوانی در آن رخ میدهد
- destination_block_id: شناسه (ID) بلوک پایهای که ادامه اجرای این فراخوانی پس از بازگشت در آن انجام میشود
هر عنصر condition به شکل زیر است:
{
"count": 4,
"covered": 2,
"not_covered_false": [],
"not_covered_true": [0, 1],
}
فیلدهای عنصر condition دارای معانی زیر هستند:
- count: تعداد نتایج شرط در این عبارت
- covered: تعداد نتایج شرط پوششدادهشده در این عبارت
- not_covered_true: شناسههای ترتیبی (ایندکسها) شروطی که در این عبارت به صورت true دیده نشدهاند
- not_covered_false: شناسههای ترتیبی (ایندکسها) شروطی که در این عبارت به صورت false دیده نشدهاند
- -H
- --human-readable
- نوشتن آمار شمارش در قالب خوانا برای انسان (مانند 24.6k).
- -k
- --use-colors
- استفاده از رنگها برای خطوطی از کد که پوشش صفر دارند. رنگ قرمز برای خطوط غیراستثنایی و رنگ فیروزهای برای خطوط استثنایی به کار میرود. همین رنگها برای بلوکهای پایه با گزینه -a نیز استفاده میشوند.
- -l
- --long-file-names
- ایجاد نام فایل طولانی برای فایلهای منبع ضمیمهشده (Included). به عنوان مثال، اگر فایل هدر x.h حاوی کد باشد و در فایل a.c ضمیمه شده باشد، اجرای gcov روی فایل a.c یک فایل خروجی به نام a.c##x.h.gcov به جای x.h.gcov تولید میکند. این گزینه زمانی مفید است که x.h در چندین فایل منبع گنجانده شده باشد و بخواهید سهم هر یک را جداگانه بررسی کنید. اگر از گزینه -p استفاده کنید، هر دو نام فایل ضمیمهکننده و ضمیمهشده به صورت مسیر کامل درج خواهند شد.
- -m
- --demangled-names
- نمایش نامهای نامگشاییشده (Demangled) توابع در خروجی. حالت پیشفرض نمایش نامهای درهمپیچیده (Mangled) توابع است.
- -M
- --filter-on-demangled
- باعث میشود --include و --exclude با نامهای نامگشاییشده (Demangled) تطبیق داده شوند. این گزینه فقط بر تطبیق الگو تأثیر میگذارد و به معنای اعمال --demangled-names نیست، اما میتوان آن را با خیال راحت همراه با آن استفاده کرد.
- -n
- --no-output
- عدم ایجاد فایل خروجی gcov.
- -o directory|file
- --object-directory directory
- --object-file file
- تعیین دایرکتوری حاوی فایلهای داده gcov یا مسیر فایل آبجکت. فایلهای داده .gcno و .gcda با استفاده از این گزینه جستجو میشوند. اگر یک دایرکتوری مشخص شود، فایلهای داده در آن دایرکتوری قرار دارند و بر اساس نام فایل ورودی (بدون پسوند آن) نامگذاری میشوند. اگر یک فایل در اینجا مشخص شود، فایلهای داده بر اساس همان فایل (بدون پسوند) نامگذاری خواهند شد.
- -p
- --preserve-paths
- حفظ اطلاعات مسیر کامل در نام فایلهای .gcov تولیدشده. بدون این گزینه فقط بخش نام فایل استفاده میشود. با این گزینه، تمام دایرکتوریها استفاده میشوند به طوری که کاراکترهای / به # تبدیل شده، اجزای دایرکتوری . حذف شده و اجزای غیرقابل حذف .. به ^ تغییر نام مییابند. این گزینه در مواردی که فایلهای منبع در چندین دایرکتوری مختلف پراکندهاند مفید است.
- -q
- --use-hotness-colors
- تولید خروجی رنگی شبیه به perf برای خطوط داغ (پراستفاده). راهنمای مقیاس رنگ در ابتدای فایل خروجی چاپ میشود.
- -r
- --relative-only
- فقط اطلاعات مربوط به فایلهای منبعی که مسیر نسبی دارند (پس از حذف پیشوند منبع) را خروجی میدهد. مسیرهای مطلق معمولاً فایلهای هدر سیستمی هستند و پوشش توابع درونخطی در آنها معمولاً حائز اهمیت نیست.
- -s directory
- --source-prefix directory
- پیشوندی برای نام فایلهای منبع که هنگام تولید فایلهای خروجی پوشش آزمون حذف میشود. این گزینه هنگام ساخت برنامه در یک دایرکتوری جداگانه مفید است، زمانی که مایل نیستید مسیر دایرکتوری منبع در تعیین نام فایلهای خروجی درج شود. توجه داشته باشید که این تشخیص پیشوند قبل از تعیین اینکه آیا فایل منبع مطلق است یا خیر اعمال میشود.
- -t
- --stdout
- خروجی دادن به خروجی استاندارد به جای ذخیره در فایلهای خروجی.
- -u
- --unconditional-branches
- هنگام نمایش احتمالات شاخهها، شاخههای نامشروط را نیز شامل میشود. شاخههای نامشروط معمولاً اهمیتی ندارند.
- -v
- --version
- نمایش شماره نسخه gcov (در خروجی استاندارد) و خروج بدون پردازش دیگر.
- -w
- --verbose
- چاپ اطلاعات با جزئیات کامل پیرامون بلوکهای پایه و یالها (Arcs).
- -x
- --hash-filenames
- هنگام استفاده از --preserve-paths، ابزار gcov از مسیر کامل فایلهای منبع برای ساخت نام فایل خروجی استفاده میکند. این امر میتواند منجر به نامهای طولانی شود که از محدودیتهای سیستمفایل فراتر روند. این گزینه نامهایی به فرم source-file##md5.gcov ایجاد میکند که در آن بخش source-file قسمت انتهایی نام فایل و بخش md5 از نام کامل دستکاریشده محاسبه میشود که در غیر این صورت استفاده میشد. این گزینه جایگزینی برای --preserve-paths در سیستمهایی با محدودیت طول نام فایل است.
دستور gcov باید در دایرکتوری جاری یکسانی با جایی که کامپایلر را فراخوانی کردهاید اجرا شود؛ در غیر این صورت قادر به یافتن فایلهای منبع نخواهد بود. ابزار gcov فایلهایی به نام mangledname.gcov در دایرکتوری جاری ایجاد میکند. این فایلها حاوی اطلاعات پوشش فایل منبع متناظر خود هستند. برای هر فایل منبع (یا هدر) حاوی کد که برای تولید فایلهای داده کامپایل شده است، یک فایل .gcov تولید میشود. بخش mangledname از نام فایل خروجی معمولاً به سادگی نام فایل منبع است، اما در صورت استفاده از گزینههای -l یا -p میتواند ساختار پیچیدهتری داشته باشد. برای جزئیات بیشتر به توضیحات آن گزینهها مراجعه کنید.
اگر gcov را با چندین فایل ورودی اجرا کنید، اطلاعات هر فایل ورودی تجمیع میشود. به طور معمول آن را با همان لیست فایلهایی که در مرحله نهایی پیوند (Link) برنامه اجرایی استفاده کردهاید اجرا میکنید.
فایلهای .gcov شامل فیلدهایی جداشده با : همراه با کد منبع برنامه هستند. قالب کلی به صورت زیر است:
<execution_count>:<line_number>:<source line text>
در صورت درخواست از طریق گزینههای خط فرمان، اطلاعات بلوک تکمیلی ممکن است بعد از هر خط بیاید. مقدار execution_count برای خطوطی که فاقد کد هستند به صورت - نشان داده میشود. خطوط اجرانشده به صورت ##### یا ===== علامتگذاری میشوند؛ بسته به اینکه آیا از مسیرهای غیراستثنایی قابل دسترسی هستند یا صرفاً از طریق مسیرهای استثنایی مانند مدیریتکنندههای استثنای C++ در دسترساند. با گزینه -a، بلوکهای اجرانشده بسته به اینکه از طریق مسیرهای غیراستثنایی یا استثنایی قابل دسترسی باشند، به صورت $$$$$ یا %%%%% علامتگذاری میشوند. بلوکهای پایه اجراشدهای که دستوری با execution_count صفر دارند با کاراکتر * خاتمه یافته و در صورت استفاده از گزینه -k با رنگ ارغوانی مشخص میشوند. این قابلیت در زبان Ada پشتیبانی نمیشود.
توجه داشته باشید که GCC میتواند بدنه توابعی را که به آنها نیازی نیست به طور کامل حذف کند -- برای مثال اگر در همه جا درونخطی (Inlined) شده باشند. چنین توابعی با - علامتگذاری میشوند که ممکن است گیجکننده باشد. از گزینههای -fkeep-inline-functions و -fkeep-static-functions استفاده کنید تا این توابع حفظ شوند و به gcov اجازه دهند مقدار execution_count آنها را به درستی نمایش دهد.
برخی از خطوط اطلاعاتی در ابتدای گزارش دارای line_number صفر هستند. این خطوط مقدماتی به فرم زیر میباشند:
-:0:<tag>:<value>
ترتیب و تعداد این خطوط مقدماتی با پیشرفت توسعه gcov گسترش خواهد یافت -- به ثابت ماندن آنها تکیه نکنید. از tag برای یافتن یک خط مقدماتی خاص استفاده کنید.
اطلاعات بلوک تکمیلی به صورت زیر است:
<tag> <information>
بخش information برای انسان خواناست، اما به گونهای طراحی شده که برای پارس ماشینی نیز به اندازه کافی ساده باشد.
هنگام چاپ درصدها، مقادیر 0% و 100% فقط زمانی چاپ میشوند که مقادیر دقیقاً به ترتیب 0% و 100% باشند. سایر مقادیری که طبق معمول به 0% یا 100% گرد میشوند، در عوض به عنوان نزدیکترین مقدار غیرمرزی چاپ میگردند.
هنگام استفاده از gcov، ابتدا باید برنامه خود را با گزینه ویژه GCC یعنی --coverage کامپایل کنید. این گزینه به کامپایلر میگوید اطلاعات تکمیلی مورد نیاز gcov (اساساً گراف جریان برنامه) را تولید کند و کدهای اضافهای را در فایلهای آبجکت جهت تولید اطلاعات پروفایلسازی بیشتر بگنجاند. این فایلهای اضافی در دایرکتوری محل قرارگیری فایل آبجکت قرار میگیرند.
اجرای برنامه باعث تولید خروجی پروفایل میشود. برای هر فایل منبع کامپایلشده با -fprofile-arcs، یک فایل همراه با پسوند .gcda در دایرکتوری فایل آبجکت قرار خواهد گرفت.
اکنون اجرای gcov با نام فایلهای منبع برنامه به عنوان آرگومان، فهرستی از کد را به همراه تواتر اجرای هر خط تولید میکند. به عنوان مثال، اگر برنامه شما tmp.cpp نام دارد، هنگام استفاده از امکانات پایه gcov چنین خروجیای را مشاهده خواهید کرد:
$ g++ --coverage tmp.cpp -c $ g++ --coverage tmp.o $ a.out $ gcov tmp.cpp -m File 'tmp.cpp' Lines executed:92.86% of 14 Creating 'tmp.cpp.gcov'
فایل tmp.cpp.gcov حاوی خروجی gcov است. این یک نمونه از آن است:
-: 0:Source:tmp.cpp
-: 0:Working directory:/home/gcc/testcase
-: 0:Graph:tmp.gcno
-: 0:Data:tmp.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include <stdio.h>
-: 2:
-: 3:template<class T>
-: 4:class Foo
-: 5:{
-: 6: public:
1*: 7: Foo(): b (1000) {}
------------------
Foo<char>::Foo():
#####: 7: Foo(): b (1000) {}
------------------
Foo<int>::Foo():
1: 7: Foo(): b (1000) {}
------------------
2*: 8: void inc () { b++; }
------------------
Foo<char>::inc():
#####: 8: void inc () { b++; }
------------------
Foo<int>::inc():
2: 8: void inc () { b++; }
------------------
-: 9:
-: 10: private:
-: 11: int b;
-: 12:};
-: 13:
-: 14:template class Foo<int>;
-: 15:template class Foo<char>;
-: 16:
-: 17:int
1: 18:main (void)
-: 19:{
-: 20: int i, total;
1: 21: Foo<int> counter;
-: 22:
1: 23: counter.inc();
1: 24: counter.inc();
1: 25: total = 0;
-: 26:
11: 27: for (i = 0; i < 10; i++)
10: 28: total += i;
-: 29:
1*: 30: int v = total > 100 ? 1 : 2;
-: 31:
1: 32: if (total != 45)
#####: 33: printf ("Failure\n");
-: 34: else
1: 35: printf ("Success\n");
1: 36: return 0;
-: 37:}
توجه داشته باشید که خط ۷ در گزارش چندین بار نشان داده شده است. اولین رخداد، تعداد کل دفعات اجرای خط را نشان میدهد و دو رخداد بعدی متعلق به نمونههای سازنده کلاس Foo هستند. همانطور که میبینید، خط ۳۰ شامل برخی بلوکهای پایه اجرانشده است و بنابراین شمارش اجرا دارای علامت ستاره است.
هنگامی که از گزینه -a استفاده میکنید، شمارش جداگانه بلوکها را دریافت خواهید کرد و خروجی به شکل زیر خواهد بود:
-: 0:Source:tmp.cpp
-: 0:Working directory:/home/gcc/testcase
-: 0:Graph:tmp.gcno
-: 0:Data:tmp.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include <stdio.h>
-: 2:
-: 3:template<class T>
-: 4:class Foo
-: 5:{
-: 6: public:
1*: 7: Foo(): b (1000) {}
------------------
Foo<char>::Foo():
#####: 7: Foo(): b (1000) {}
------------------
Foo<int>::Foo():
1: 7: Foo(): b (1000) {}
------------------
2*: 8: void inc () { b++; }
------------------
Foo<char>::inc():
#####: 8: void inc () { b++; }
------------------
Foo<int>::inc():
2: 8: void inc () { b++; }
------------------
-: 9:
-: 10: private:
-: 11: int b;
-: 12:};
-: 13:
-: 14:template class Foo<int>;
-: 15:template class Foo<char>;
-: 16:
-: 17:int
1: 18:main (void)
-: 19:{
-: 20: int i, total;
1: 21: Foo<int> counter;
1: 21-block 0
-: 22:
1: 23: counter.inc();
1: 23-block 0
1: 24: counter.inc();
1: 24-block 0
1: 25: total = 0;
-: 26:
11: 27: for (i = 0; i < 10; i++)
1: 27-block 0
11: 27-block 1
10: 28: total += i;
10: 28-block 0
-: 29:
1*: 30: int v = total > 100 ? 1 : 2;
1: 30-block 0
%%%%%: 30-block 1
1: 30-block 2
-: 31:
1: 32: if (total != 45)
1: 32-block 0
#####: 33: printf ("Failure\n");
%%%%%: 33-block 0
-: 34: else
1: 35: printf ("Success\n");
1: 35-block 0
1: 36: return 0;
1: 36-block 0
-: 37:}
در این حالت، هر بلوک پایه فقط روی یک خط نشان داده میشود -- آخرین خط بلوک. یک بلوک چندخطی فقط به شمارش اجرای همان خط آخر کمک میکند و سایر خطوط فاقد کد به نظر میرسند، مگر اینکه بلوکهای قبلی در آن خطوط پایان یافته باشند. شمارش کل اجرای یک خط نشان داده میشود و خطوط بعدی شمارش اجرا برای بلوکهای مجزایی را نشان میدهند که در آن خط پایان مییابند. در صورت استفاده از گزینه -b، پس از هر بلوک، تعداد شاخهها و فراخوانیهای آن بلوک نمایش داده خواهد شد.
به دلیل نحوه سنجش فراخوانیها توسط GCC، ممکن است شمارش فراخوانی بعد از خطی بدون بلوکهای مجزا نمایش داده شود. همانطور که میبینید، خط ۳۳ حاوی یک بلوک پایه است که اجرا نشده است.
هنگامی که از گزینه -b استفاده میکنید، خروجی به صورت زیر خواهد بود:
-: 0:Source:tmp.cpp
-: 0:Working directory:/home/gcc/testcase
-: 0:Graph:tmp.gcno
-: 0:Data:tmp.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include <stdio.h>
-: 2:
-: 3:template<class T>
-: 4:class Foo
-: 5:{
-: 6: public:
1*: 7: Foo(): b (1000) {}
------------------
Foo<char>::Foo():
function Foo<char>::Foo() called 0 returned 0% blocks executed 0%
#####: 7: Foo(): b (1000) {}
------------------
Foo<int>::Foo():
function Foo<int>::Foo() called 1 returned 100% blocks executed 100%
1: 7: Foo(): b (1000) {}
------------------
2*: 8: void inc () { b++; }
------------------
Foo<char>::inc():
function Foo<char>::inc() called 0 returned 0% blocks executed 0%
#####: 8: void inc () { b++; }
------------------
Foo<int>::inc():
function Foo<int>::inc() called 2 returned 100% blocks executed 100%
2: 8: void inc () { b++; }
------------------
-: 9:
-: 10: private:
-: 11: int b;
-: 12:};
-: 13:
-: 14:template class Foo<int>;
-: 15:template class Foo<char>;
-: 16:
-: 17:int
function main called 1 returned 100% blocks executed 81%
1: 18:main (void)
-: 19:{
-: 20: int i, total;
1: 21: Foo<int> counter;
call 0 returned 100%
branch 1 taken 100% (fallthrough)
branch 2 taken 0% (throw)
-: 22:
1: 23: counter.inc();
call 0 returned 100%
branch 1 taken 100% (fallthrough)
branch 2 taken 0% (throw)
1: 24: counter.inc();
call 0 returned 100%
branch 1 taken 100% (fallthrough)
branch 2 taken 0% (throw)
1: 25: total = 0;
-: 26:
11: 27: for (i = 0; i < 10; i++)
branch 0 taken 91% (fallthrough)
branch 1 taken 9%
10: 28: total += i;
-: 29:
1*: 30: int v = total > 100 ? 1 : 2;
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
-: 31:
1: 32: if (total != 45)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 33: printf ("Failure\n");
call 0 never executed
branch 1 never executed
branch 2 never executed
-: 34: else
1: 35: printf ("Success\n");
call 0 returned 100%
branch 1 taken 100% (fallthrough)
branch 2 taken 0% (throw)
1: 36: return 0;
-: 37:}
برای هر تابع، خطی چاپ میشود که نشان میدهد تابع چند بار فراخوانی شده، چند بار بازگشته و چند درصد از بلوکهای تابع اجرا شدهاند.
برای هر بلوک پایه، خطی پس از آخرین خط بلوک پایه چاپ میشود که شاخه یا فراخوانی خاتمهدهنده آن بلوک را توصیف میکند. اگر چندین بلوک پایه در یک خط منبع پایان یابند، ممکن است چندین شاخه و فراخوانی برای آن خط لیست شوند. در این حالت به هر یک از شاخهها و فراخوانیها شمارهای اختصاص داده میشود. راه سادهای برای نگاشت این شاخهها و فراخوانیها به ساختارهای کد منبع وجود ندارد، اما به طور کلی کوچکترین شماره شاخه یا فراخوانی متناظر با چپترین ساختار در خط منبع خواهد بود.
برای یک شاخه، در صورتی که حداقل یک بار اجرا شده باشد، درصدی نشاندهنده نسبت تعداد دفعات طی شدن شاخه به تعداد کل دفعات اجرای آن چاپ خواهد شد؛ در غیر این صورت پیام "never executed" چاپ میشود.
برای یک فراخوانی، در صورتی که حداقل یک بار اجرا شده باشد، درصدی نشاندهنده نسبت تعداد دفعات بازگشت فراخوانی به تعداد دفعات اجرای آن چاپ میشود. این مقدار معمولاً 100% است، اما ممکن است برای توابعی که "exit" یا "longjmp" را فراخوانی میکنند کمتر باشد؛ زیرا ممکن است با هر بار فراخوانی بازنگردند.
هنگامی که از گزینه -g استفاده میکنید، خروجی شما شبیه به این خواهد بود:
$ gcov -t -m -g tmp
-: 0:Source:tmp.cpp
-: 0:Graph:tmp.gcno
-: 0:Data:tmp.gcda
-: 0:Runs:1
-: 1:#include <stdio.h>
-: 2:
-: 3:int
1: 4:main (void)
-: 5:{
-: 6: int i, total;
1: 7: total = 0;
-: 8:
11: 9: for (i = 0; i < 10; i++)
condition outcomes covered 2/2
10: 10: total += i;
-: 11:
1*: 12: int v = total > 100 ? 1 : 2;
condition outcomes covered 1/2
condition 0 not covered (true)
-: 13:
1*: 14: if (total != 45 && v == 1)
condition outcomes covered 1/4
condition 0 not covered (true)
condition 1 not covered (true false)
#####: 15: printf ("Failure\n");
-: 16: else
1: 17: printf ("Success\n");
1: 18: return 0;
-: 19:}
برای هر شرط، تعداد نتایج طیشده و کل نتایج چاپ میشود و در صورت وجود نتایج پوششدادهنشده، خطی برای هر شرط نمایش داده میشود که نتیجه پوششدادهنشده را درون پرانتز نشان میدهد. شرطها با ایندکس خود شناخته میشوند -- ایندکس 0 چپترین شرط است. در عبارت "a || (b && c)"، متغیر a شرط 0، b شرط 1 و c شرط 2 است.
یک نتیجه زمانی پوششدادهشده تلقی میشود که تأثیر مستقلی بر تصمیم داشته باشد؛ این مفهوم به عنوان پوشش MC/DC پوششی (Masking Modified Condition/Decision Coverage) نیز شناخته میشود. در این مثال، تصمیم به true ارزیابی شده و a ارزیابی میشود اما پوشش داده نمیشود. دلیل این امر آن است که a نمیتواند به طور مستقل بر تصمیم تأثیر بگذارد -- برای تغییر نتیجه تصمیم، هر دو مقدار a و b باید تغییر کنند.
$ gcov -t -m -g tmp
-: 0:Source:tmp.c
-: 0:Graph:tmp.gcno
-: 0:Data:tmp.gcda
-: 0:Runs:1
-: 1:#include <stdio.h>
-: 2:
1: 3:int main()
-: 4:{
1: 5: int a = 1;
1: 6: int b = 0;
-: 7:
1: 8: if (a && b)
condition outcomes covered 1/4
condition 0 not covered (true false)
condition 1 not covered (true)
#####: 9: printf ("Success!\n");
-: 10: else
1: 11: printf ("Failure!\n");
-: 12:}
هنگامی که با --coverage -fpath-coverage کامپایل کرده و از گزینه -e استفاده میکنید، خروجی شما به شکل زیر خواهد بود:
$ gcov -t -e tmp
-: 0:Source:tmp.cpp
-: 0:Graph:tmp.gcno
-: 0:Data:tmp.gcda
-: 0:Runs:1
-: 1:#include <stdio.h>
-: 2:
paths covered 4 of 15
1: 3:int main ()
-: 4:{
-: 5: int i, total;
1: 6: total = 0;
-: 7:
11: 8: for (i = 0; i < 10; i++)
10: 9: total += i;
-: 10:
1*: 11: int v = total > 100 ? 1 : 2;
-: 12:
1*: 13: if (total != 45 && v == 1)
#####: 14: printf ("Failure\n");
-: 15: else
1: 16: printf ("Success\n");
1: 17: return 0;
-: 18:}
این خروجی برای درک تقریبی بخشهای فاقد پوشش و آزمایش نحوه تغییر پوشش با ورودیهای گوناگون مفید است. گزینه --prime-paths-source ابزار مفیدی برای درک مسیرهاست.
$ gcov -t --prime-paths-source tmp
-: 0:Source:tmp.cpp
-: 0:Graph:tmp.gcno
-: 0:Data:tmp.gcda
-: 0:Runs:1
-: 1:#include <stdio.h>
-: 2:
paths covered 4 of 15
path 1:
BB 2: 3:int main ()
BB 2: 6: total = 0;
BB 2: 8: for (i = 0; i < 10; i++)
BB 4: (false) 8: for (i = 0; i < 10; i++)
BB 5: (true) 11: int v = total > 100 ? 1 : 2;
BB 6: 11: int v = total > 100 ? 1 : 2;
BB 8: (true) 13: if (total != 45 && v == 1)
BB 9: (true) 13: if (total != 45 && v == 1)
BB 10: 14: printf ("Failure\n");
BB 12: 17: return 0;
در این حالت، gcov جزئیات مسیرهای غایب را چاپ میکند. ستون اول توالی بلوکهای پایه (BB) را فهرست میکند. ستون دوم تصمیم اتخاذشده در آن خط (در صورت وجود) است. ستونهای نهایی شماره خط و خود خط کد هستند. این اطلاعات برای درک مسیرها، به ویژه مسیرهایی که پوشش آنها دشوار یا حتی غیرقابل دسترسی هستند، مفید است. اگر یک خط بخشی از چندین بلوک پایه باشد، ممکن است تکرار شود؛ مانند حلقه "for". این حالت برای انسان طراحی شده و در درک اینکه چه کدی در حین آزمون یا با ورودیهای دادهشده اجرا میشود عالی است. این خروجی بسیار مفصل است و برای تمرکز روی توابع خاص میتوان آن را با فیلترهای --include و --exclude ترکیب کرد.
خروجی فشردهتری با --prime-paths-lines در دسترس است که به شکل زیر خواهد بود:
-: 0:Source:tmp.cpp
-: 0:Graph:tmp.gcno
-: 0:Data:tmp.gcda
-: 0:Runs:1
-: 1:#include <stdio.h>
-: 2:
paths covered 4 of 15
path 1 not covered: lines 8 8(false) 11(true) 11 13(true) 13(true) 14 17
path 2 not covered: lines 8 8(false) 11(true) 11 13(true) 13(false) 16 17
path 3 not covered: lines 8 8(false) 11(true) 11 13(false) 16 17
path 4 not covered: lines 8 8(false) 11(false) 11 13(true) 13(true) 14 17
path 5 not covered: lines 8 8(false) 11(false) 11 13(true) 13(false) 16 17
path 6 not covered: lines 8 8(false) 11(false) 11 13(false) 16 17
path 8 not covered: lines 9 8(false) 11(true) 11 13(true) 13(true) 14 17
path 9 not covered: lines 9 8(false) 11(true) 11 13(true) 13(false) 16 17
path 10 not covered: lines 9 8(false) 11(true) 11 13(false) 16 17
path 11 not covered: lines 9 8(false) 11(false) 11 13(true) 13(true) 14 17
path 12 not covered: lines 9 8(false) 11(false) 11 13(true) 13(false) 16 17
1: 3:int main ()
-: 4:{
.Ve
در این حالت، هر مسیر غایب با استفاده از خطوط و تصمیمات، مشابه --prime-paths-source اما در یک خط چاپ میشود. این حالت دید کلی مناسبی از مسیرها و ردیابی چگونگی آزمایش کد توسط آزمونها و ورودیهای مختلف فراهم میسازد.
شمارشهای اجرا انباشتهشونده (Cumulative) هستند. اگر برنامه نمونه دوباره بدون حذف فایل .gcda اجرا شود، تعداد دفعات اجرای هر خط در منبع به نتایج اجرای قبلی اضافه خواهد شد. این ویژگی از چندین جهت کاربردی است؛ به عنوان مثال میتواند برای تجمیع دادهها در چندین بار اجرای برنامه به عنوان بخشی از یک مجموعه اعتبارسنجی آزمون، یا ارائه اطلاعات دقیقتر بلندمدت در طول اجرای مکرر برنامه استفاده شود.
دادههای موجود در فایلهای .gcda درست پیش از خروج برنامه ذخیره میشوند. برای هر فایل منبع کامپایلشده با -fprofile-arcs، کد پروفایلسازی ابتدا تلاش میکند یک فایل موجود .gcda را بخواند؛ اگر فایل با فایل اجرایی مطابقت نداشته باشد (تعداد شمارش بلوکهای پایه متفاوت باشد) محتویات فایل را نادیده میگیرد. سپس شمارشهای اجرای جدید را اضافه کرده و در نهایت دادهها را در فایل مینویسد.
میتوانید با استفاده از --include و --exclude گزارش را به زیرمجموعهای از توابع محدود کنید. این کار هنگام ترکیب با --stdout برای درک رفتار و پوشش یک تابع خاص بسیار مفید است؛ به این صورت که آزمایشی را اجرا کرده، خروجی gcov را مشاهده میکنید، ورودی دیگری را آزمایش کرده و دوباره gcov را اجرا مینمایید.
$ gcov -m --stdout --include inc tmp
-: 0:Source:tmp.cpp
-: 0:Graph:tmp.gcno
-: 0:Data:tmp.gcda
-: 0:Runs:1
2*: 8: void inc () { b++; }
------------------
Foo<char>::inc():
#####: 8: void inc () { b++; }
------------------
Foo<int>::inc():
2: 8: void inc () { b++; }
------------------
ابزار gcov به طور پیشفرض با نامهای درهمپیچیده (Mangled) تطبیق داده میشود که میتوانید آن را با فلگ -M کنترل کنید. توجه داشته باشید که تطبیق الگو و گزارشدهی مستقل از هم هستند؛ بنابراین میتوانید در حین چاپ نامهای نامگشاییشده، تطبیق را بر اساس نامهای درهمپیچیده انجام دهید و برعکس. برای گزارش نمونه "int" از کلاس "Foo" با تطبیق روی نامهای درهمپیچیده و نامگشاییشده:
$ gcov -t -m -M tmp --include 'Foo<int>'
-: 0:Source:tmp.cpp
-: 0:Graph:tmp.gcno
-: 0:Data:tmp.gcda
-: 0:Runs:1
1: 7: Foo(): b (1000) {}
2: 8: void inc () { b++; }
$ gcov -t -m tmp --include 'FooIi'
-: 0:Source:tmp.cpp
-: 0:Graph:tmp.gcno
-: 0:Data:tmp.gcda
-: 0:Runs:1
1: 7: Foo(): b (1000) {}
2: 8: void inc () { b++; }
آرگومانهای --include و --exclude عبارات باقاعده گسترده هستند (مانند grep -E)، بنابراین الگوی "in.?" با هر دوی "inc" و "main" تطبیق دارد. اگر با -M استفاده شود، تمام نمونههای "int" از "Foo" نیز مطابقت خواهند داشت. گزینههای --include و --exclude را میتوان چندین بار استفاده کرد و اگر نامی با چندین فیلتر مطابقت داشته باشد، آخرین مورد اولویت خواهد داشت. به عنوان مثال، برای مطابقت با "main" و نمونه "int" از "inc"، در حالی که از سازنده "Foo" صرفنظر میشود:
$ gcov -t -m -M --include in --exclude Foo --include '<int>::inc' tmp
-: 0:Source:tmp.cpp
-: 0:Graph:tmp.gcno
-: 0:Data:tmp.gcda
-: 0:Runs:1
2: 8: void inc () { b++; }
1: 18:main (void)
-: 19:{
-: 20: int i, total;
1: 21: Foo<int> counter;
-: 22:
1: 23: counter.inc();
1: 24: counter.inc();
1: 25: total = 0;
-: 26:
11: 27: for (i = 0; i < 10; i++)
10: 28: total += i;
-: 29:
1*: 30: int v = total > 100 ? 1 : 2;
-: 31:
1: 32: if (total != 45)
#####: 33: printf ("Failure\n");
-: 34: else
1: 35: printf ("Success\n");
1: 36: return 0;
استفاده از gcov با بهینهسازی GCC
اگر قصد دارید از gcov برای کمک به بهینهسازی کد خود استفاده کنید، ابتدا باید برنامه را با گزینه ویژه GCC یعنی --coverage کامپایل نمایید. جدا از آن میتوانید از هر گزینه دیگر GCC استفاده کنید؛ اما اگر میخواهید اثبات کنید که تکتک خطوط برنامه اجرا شدهاند، نباید همزمان با بهینهسازی کامپایل کنید. در برخی سیستمها بهینهساز میتواند برخی خطوط ساده کد را با ترکیب آنها با سایر خطوط حذف کند. به عنوان مثال کدی مانند این:
if (a != b) c = 1; else c = 0;
روی برخی ماشینها میتواند به یک دستورالعمل اسمبلی کامپایل شود. در این حالت هیچ راهی برای gcov وجود ندارد تا شمارشهای اجرای جداگانهای برای هر خط محاسبه کند؛ زیرا برای هر خط کد مجزایی وجود ندارد. بنابراین در صورت کامپایل برنامه با بهینهسازی، خروجی gcov به این صورت خواهد بود:
100: 12:if (a != b) 100: 13: c = 1; 100: 14:else 100: 15: c = 0;
خروجی نشان میدهد این بلوک کد که توسط بهینهساز ترکیب شده، ۱۰۰ بار اجرا شده است. از یک جهت این نتیجه درست است؛ چرا که تنها یک دستورالعمل نماینده همه این چهار خط بوده است. با این حال خروجی نشان نمیدهد که چند بار نتیجه 0 و چند بار نتیجه 1 بوده است.
توابع درونخطیشونده (Inlineable Functions) میتوانند شمارش خطوط غیرمنتظرهای ایجاد کنند. شمارش خطوط برای کد منبع تابع درونخطی نمایش داده میشود، اما آنچه نشان داده میشود به این بستگی دارد که تابع در کجا درونخطی شده یا اصلاً درونخطی نشده است.
اگر تابع درونخطی نشود، کامپایلر باید یک نسخه مستقل (Out-of-line) از تابع را در هر فایل آبجکتی که به آن نیاز دارد صادر کند. اگر هر دوی fileA.o و fileB.o شامل بدنه مستقل تابع درونخطی باشند، هر دو نیز شامل شمارش پوشش برای آن تابع خواهند بود. هنگامی که fileA.o و fileB.o به هم پیوند داده میشوند، پیونددهنده (Linker) در بسیاری از سیستمها یکی از آن بدنههای مستقل را برای تمام فراخوانیهای آن تابع انتخاب کرده و دیگری را حذف یا نادیده میگیرد. متأسفانه شمارندههای پوشش را برای بدنه استفادهنشده تابع حذف نمیکند. بنابراین هنگام اندازهگیری، همه کاربردهای آن تابع به جز یکی، شمارش صفر را نشان خواهند داد.
اگر تابع در چندین مکان درونخطی شود، ممکن است ساختار بلوک در هر مکان یکسان نباشد. به عنوان مثال یک شرط ممکن است در برخی موارد در زمان کامپایل قابل محاسبه باشد. از آنجا که پوشش تمام استفادههای تابع درونخطی برای همان خطوط منبع یکسان نشان داده میشود، خود شمارش خطوط ممکن است ناسازگار به نظر برسد.
برنامههایی با اجرای طولانی میتوانند از امکانات "__gcov_reset" و "__gcov_dump" برای محدود کردن جمعآوری پروفایل به بخش مورد نظر از برنامه استفاده کنند. فراخوانی "__gcov_reset(void)" تمام شمارندههای پروفایل زمان اجرا را صفر میکند و فراخوانی "__gcov_dump(void)" باعث میشود اطلاعات پروفایل جمعآوریشده تا آن لحظه در فایلهای خروجی .gcda ذخیره شود. برنامههای مجهز به ابزار دقیق از یک تخریبکننده ایستا (Static Destructor) با اولویت ۹۹ برای فراخوانی تابع "__gcov_dump" استفاده میکنند. بنابراین "__gcov_dump" پس از همه تخریبکنندههای ایستای تعریفشده توسط کاربر و همچنین مدیریتکنندههای ثبتشده با "atexit" اجرا میشود.
اگر یک فایل اجرایی یک شیء مشترک پویا را از طریق قابلیت dlopen بارگذاری کند، گزینه -Wl,--dynamic-list-data برای تخلیه تمام دادههای پروفایل مورد نیاز است.
کتابخانه زمان اجرای پروفایلسازی خطاهای مختلف مربوط به دستکاری پروفایل و ذخیرهسازی آن را گزارش میدهد. در صورت استفاده از متغیر محیطی، خطاها در خروجی خطای استاندارد یا فایل GCOV_ERROR_FILE چاپ میشوند. برای پایان دادن فوری برنامه پس از وقوع خطا، متغیر محیطی GCOV_EXIT_AT_ERROR را تنظیم کنید. این کار به کاربران کمک میکند تا تداخل پروفایلها را که منجر به پروفایل گمراهکننده میشود پیدا کنند.
همچنین ببینید (SEE ALSO)
gpl(7), gfdl(7), fsf-funding(7), gcc(1) و مدخل Info برای gcc.
حق نشر (COPYRIGHT)
حق نشر © 1996-2025 Free Software Foundation, Inc.
مجوز کپی، توزیع و/یا تغییر این سند تحت شرایط مجوز مستندات آزاد گنو (GNU Free Documentation License)، نسخه ۱.۳ یا هر نسخه بعدی منتشر شده توسط بنیاد نرمافزار آزاد اعطا میشود؛ بدون بخشهای تغییرناپذیر، بدون متون روی جلد و بدون متون پشت جلد. نسخهای از این مجوز در صفحه راهنمای gfdl(7) گنجانده شده است.
(الف) متن روی جلد FSF عبارت است از:
A GNU Manual
(ب) متن پشت جلد FSF عبارت است از:
You have freedom to copy and modify this GNU Manual, like GNU software. Copies published by the Free Software Foundation raise funds for GNU development.
| 2025-08-08 | gcc-15.2.0 |