| GCOV(1) | GNU | GCOV(1) |
نام (NAME)
gcov - ابزار تست پوشش کد منبع
خلاصه دستور (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 یک برنامه آزمون پوشش کد است. از آن همراه با GCC برای تحلیل برنامههای خود استفاده کنید تا به ایجاد کدی کارآمدتر و با اجرای سریعتر کمک کرده و بخشهای آزمودهنشده برنامه خود را کشف نمایید. میتوانید از gcov به عنوان یک ابزار پروفایلینگ استفاده کنید تا دریابید تلاشهای بهینهسازی شما در کجای کد بیشترین تأثیر را خواهد داشت. همچنین میتوانید از gcov همراه با ابزار پروفایلینگ دیگر، یعنی gprof، برای ارزیابی اینکه کدام بخشهای کد شما بیشترین میزان زمان محاسباتی را مصرف میکنند استفاده کنید.
ابزارهای پروفایلینگ به شما در تحلیل عملکرد کدتان کمک میکنند. با استفاده از یک پروفایلر مانند gcov یا gprof، میتوانید به برخی از آمارهای پایه عملکرد دست یابید، مانند:
- هر خط از کد هر چند وقت یکبار اجرا میشود
- چه خطوطی از کد در عمل اجرا میشوند
- هر بخش از کد چه مقدار زمان محاسباتی مصرف میکند
هنگامی که این موارد را درباره نحوه کارکرد کد خود پس از کامپایل دانستید، میتوانید هر ماژول را بررسی کنید تا ببینید کدام ماژولها باید بهینهسازی شوند. gcov به شما کمک میکند تعیین کنید که کار بهینهسازی را روی کدام بخشها متمرکز کنید.
توسعهدهندگان نرمافزار همچنین از تست پوشش کد همراه با مجموعههای آزمون استفاده میکنند تا مطمئن شوند نرمافزار برای انتشار واقعاً به اندازه کافی مناسب است. مجموعههای آزمون میتوانند بررسی کنند که برنامه همانطور که انتظار میرود کار میکند؛ یک برنامه پوشش کد بررسی میکند که چه مقدار از برنامه توسط مجموعه آزمون اجرا شده است. سپس توسعهدهندگان میتوانند مشخص کنند چه نوع مواردی باید به مجموعههای آزمون اضافه شوند تا هم آزمونهای بهتری ایجاد شود و هم محصول نهایی بهتری حاصل گردد.
اگر قصد دارید از gcov استفاده کنید، باید کد خود را بدون بهینهسازی کامپایل نمایید؛ زیرا بهینهسازی با ترکیب چند خط کد در یک تابع، ممکن است اطلاعات کافی مورد نیاز شما را برای جستجوی «نقاط داغ» (hot spots) که در آن کد زمان زیادی از رایانه را مصرف میکند، ارائه ندهد. به همین ترتیب، از آنجا که gcov آمارها را بر پایه خط (در پایینترین وضوح) جمعآوری میکند، با سبک برنامهنویسیای بهترین کارایی را دارد که در هر خط تنها یک دستور قرار میگیرد. اگر از ماکروهای پیچیدهای استفاده کنید که به حلقهها یا دیگر ساختارهای کنترلی بسط مییابند، آمارها کمتر مفید خواهند بود---آنها تنها در همان خطی که فراخوانی ماکرو ظاهر شده است گزارش میدهند. اگر ماکروهای پیچیده شما رفتاری شبیه به توابع دارند، میتوانید برای رفع این مشکل آنها را با توابع درونخطی (inline) جایگزین کنید.
برنامه gcov یک فایل لاگ به نام sourcefile.gcov ایجاد میکند که نشان میدهد هر خط از یک فایل منبع sourcefile.c چند بار اجرا شده است. میتوانید از این فایلهای گزارش همراه با gprof برای کمک به تنظیم دقیق کارایی برنامههای خود بهره ببرید. gprof اطلاعات زمانبندی را ارائه میدهد که میتوانید همراه با اطلاعات دریافتشده از gcov استفاده نمایید.
برنامه gcov تنها روی کدهایی کار میکند که با GCC کامپایل شده باشند. این ابزار با هیچ سازوکار پروفایلینگ یا آزمون پوشش کد دیگری سازگار نیست.
گزینهها (OPTIONS)
- -a
- --all-blocks
- تعداد دفعات اجرای مجزا برای هر بلوک پایه را مینویسد. به طور معمول gcov تعداد دفعات اجرا را فقط برای بلوکهای اصلی یک خط در خروجی میآورد. با این گزینه میتوانید مشخص کنید آیا بلوکهای درون یک خط منفرد اجرا نمیشوند یا خیر.
- -b
- --branch-probabilities
- بسامد انشعابها را در فایل خروجی و خلاصه اطلاعات انشعاب را در خروجی استاندارد مینویسد. این گزینه به شما اجازه میدهد ببینید هر انشعاب در برنامه شما هر چند وقت یکبار طی شده است. انشعابهای بدون شرط نشان داده نخواهند شد، مگر اینکه گزینه -u داده شده باشد.
- -c
- --branch-counts
- بسامد انشعابها را به صورت تعداد انشعابهای طیشده مینویسد، نه درصد انشعابهای طیشده.
- -g
- --conditions
- پوشش شرطها را در فایل خروجی و اطلاعات خلاصه شرطها را در خروجی استاندارد مینویسد. این گزینه به شما امکان میدهد ببینید آیا شرایط موجود در برنامه شما حداقل یکبار تأثیر مستقلی بر نتیجه عبارت بولی داشتهاند یا خیر (پوشش شرط/تصمیم اصلاحشده یا MC/DC). این گزینه مستلزم آن است که کد منبع را با -fcondition-coverage کامپایل کنید.
- -e
- --prime-paths
- پوشش مسیر را در فایل خروجی و اطلاعات خلاصه مسیر را در خروجی استاندارد مینویسد. این گزینه به شما امکان میدهد ببینید چند مسیر اصلی حداقل یک بار طی شدهاند. یک مسیر، توالیای از بلوکهای پایه است. یک مسیر در صورتی ساده است که هیچ بلوک تکراری نداشته باشد (بدون حلقه)، به جز احتمالاً اولین و آخرین بلوک، و در صورتی یک مسیر اصلی (prime path) است که مسیری ساده با حداکثر طول باشد. برای خروجی عادی، این گزینه تنها تعداد مسیرهای پوششدادهشده را شامل میشود. برای اطلاعات دقیقتر درباره مسیرها میتوانید از --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 شامل پارامترهای قالب و نوع بازگشتی ابتدایی نیستند، اما احتمالاً در آینده اصلاح خواهد شد.
هر 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: در صورتی که انشعاب یک انشعاب عبور مستقیم (fall through) باشد true است
- throw: در صورتی که انشعاب یک انشعاب استثنایی باشد true است
- isource_block_id: شناسه بلوک پایهای که این انشعاب در آن رخ میدهد
- destination_block_id: شناسه بلوک پایهای که این انشعاب به آن جهش میکند
هر call ساختار زیر را دارد:
{
"destination_block_id": 1,
"returned": 11,
"source_block_id": 13
}
فیلدهای عنصر call دارای معانی زیر هستند:
- returned: تعداد دفعاتی که یک فراخوانی تابع بازگشته است (تعداد فراخوانی برابر با line::count است)
- isource_block_id: شناسه بلوک پایهای که این فراخوانی در آن رخ میدهد
- destination_block_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 به جای x.h.gcov، یک فایل خروجی به نام a.c##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 را با چندین فایل ورودی فراخوانی کنید، سهم هر فایل ورودی جمع زده میشود. معمولاً شما آن را با همان فهرست فایلهایی فراخوانی میکنید که در پیوند نهایی برنامه اجرایی خود استفاده کردهاید.
فایلهای .gcov شامل فیلدهایی هستند که با : همراه با کد منبع برنامه جدا شدهاند. قالب آن به صورت زیر است:
<execution_count>:<line_number>:<source line text>
در صورت درخواست از طریق گزینه خط فرمان، ممکن است اطلاعات بلوک اضافی پس از هر خط بیاید. مقدار execution_count برای خطوط فاقد کد - است. خطوط اجرا نشده بسته به اینکه از طریق مسیرهای غیراستثنایی قابل دسترس باشند یا تنها از طریق مسیرهای استثنایی مانند گردانندههای استثنای ++C، به ترتیب با ##### یا ===== مشخص میشوند. در صورت ارائه گزینه -a، بلوکهای اجرا نشده بسته به اینکه یک بلوک پایه از طریق مسیرهای غیراستثنایی یا استثنایی قابل دسترس باشد با $$$$$ یا %%%%% مشخص میگردند. بلوکهای پایه اجرا شده که دارای دستوری با execution_count صفر هستند، با نویسه * خاتمه مییابند و با گزینه -k به رنگ سرخابی (magenta) نشان داده میشوند. این قابلیت در Ada پشتیبانی نمیشود.
توجه داشته باشید که GCC میتواند بدنه توابعی را که مورد نیاز نیستند کاملاً حذف کند -- برای مثال اگر در همهجا درونخطی (inline) شده باشند. چنین توابعی با - مشخص میشوند که میتواند گیجکننده باشد. از گزینههای -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 (اساساً یک گراف جریان از برنامه) را تولید کند و همچنین کدهای اضافی را در فایلهای شیء جهت تولید اطلاعات پروفایلینگ اضافی مورد نیاز 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 فراخوانیها را ابزارگذاری (instrument) میکند، تعداد فراخوانی میتواند پس از خطی بدون بلوکهای مجزا نشان داده شود. همانطور که میبینید، خط ۳۳ حاوی یک بلوک پایه است که اجرا نشده است.
هنگامی که از گزینه -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:}
برای هر شرط، تعداد برآمدهای طیشده و برآمدهای کل چاپ میشود، و در صورتی که برآمدهای پوششدادهنشدهای وجود داشته باشد، خطی برای هر شرط چاپ میشود که برآمد پوششدادهنشده را درون پرانتز نشان میدهد. شرایط با اندیس خود مشخص میشوند -- اندیس ۰ چپترین شرط است. در "a || (b && c)"، بخش a شرط ۰، بخش b شرط ۱، و c شرط ۲ است.
یک برآمد در صورتی پوششدادهشده تلقی میشود که تأثیر مستقلی بر تصمیم داشته باشد، که به عنوان MC/DC ماسکشده (پوشش شرط/تصمیم اصلاحشده) نیز شناخته میشود. در این مثال، تصمیم به 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:{
در این حالت، هر مسیر گمشده با استفاده از خطوط و تصمیمات مانند --prime-paths-source اما در یک خط منفرد باز میشود. این حالت دید کلی مناسبی روی مسیرها و برای ردیابی نحوه آزموده شدن کد توسط آزمونها و ورودیهای مختلف فراهم میسازد.
تعداد دفعات اجرا تجمعی هستند. اگر برنامه نمونه دوباره بدون حذف فایل .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 آن را کنترل کنید. توجه داشته باشید که تطبیق و گزارشدهی مستقل هستند، بنابراین میتوانید روی نامهای درهمریخته مطابقت دهید در حالی که نامهای رمزگشاییشده (demangled) را چاپ میکنید، و برعکس. برای گزارشگیری از نمونهسازی "int" از "Foo" با تطبیق روی نامهای mangled و demangled:
$ 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;
خروجی نشان میدهد این بلوک کد که با بهینهسازی ترکیب شده است، ۱۰۰ بار اجرا شده است. از یک دیدگاه این نتیجه درست است، زیرا تنها یک دستورالعمل ماشین نشاندهنده تمام این چهار خط بوده است. با این حال، خروجی مشخص نمیکند که نتیجه چند بار ۰ و چند بار ۱ بوده است.
توابع قابل درونخطیسازی (inlineable) میتوانند تعداد خطوط غیرمنتظرهای ایجاد کنند. شمارش خطوط برای کد منبع تابع قابل درونخطیسازی نشان داده میشود، اما آنچه نشان داده میشود به این بستگی دارد که تابع در کجا درونخطی شده باشد، یا اینکه اصلاً درونخطی نشده باشد.
اگر تابع درونخطی نشود، کامپایلر باید یک کپی خارج از خط (out of line) از تابع را در هر فایل شیئی که به آن نیاز دارد تولید کند. اگر fileA.o و fileB.o هر دو حاوی بدنههای خارج از خط یک تابع درونخطیپذیر خاص باشند، هر دو نیز حاوی شمارشهای پوشش برای آن تابع خواهند بود. هنگامی که fileA.o و fileB.o با هم پیوند داده میشوند، پیونددهنده در بسیاری از سیستمها یکی از آن بدنههای خارج از خط را برای تمام فراخوانیهای آن تابع انتخاب کرده و دیگری را حذف یا نادیده میگیرد. متأسفانه، شمارندههای پوشش را برای بدنه استفادهنشده تابع حذف نخواهد کرد. از این رو هنگام ابزارگذاری، همه به جز یکی از کاربردهای آن تابع، شمارش صفر را نشان خواهند داد.
اگر تابع در چندین مکان درونخطی شود، ساختار بلوک در هر مکان ممکن است یکسان نباشد. برای مثال، ممکن است یک شرط اکنون در برخی موارد در زمان کامپایل قابل محاسبه باشد. از آنجا که پوشش تمام استفادههای تابع درونخطی برای همان خطوط منبع نمایش داده خواهد شد، خود شمارش خطوط ممکن است متناقض به نظر برسند.
برنامههای با اجرای طولانی میتوانند از امکانات "__gcov_reset" و "__gcov_dump" برای محدود کردن جمعآوری پروفایل به ناحیه مورد نظر برنامه استفاده نمایند. فراخوانی "__gcov_reset(void)" تمام شمارندههای پروفایل زمان اجرا را صفر میکند، و فراخوانی "__gcov_dump(void)" باعث میشود اطلاعات پروفایل جمعآوریشده در آن نقطه در فایلهای خروجی .gcda تخلیه شوند. برنامههای ابزارگذاریشده از یک تخریبکننده استاتیک با اولویت ۹۹ برای فراخوانی تابع "__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)
Copyright (c) 1996-2026 Free Software Foundation, Inc.
اجازه کپی، توزیع و/یا تغییر این سند تحت شرایط مجوز مستندات آزاد گنو (GNU Free Documentation License)، نگارش 1.3 یا هر نگارش بعدی منتشرشده توسط بنیاد نرمافزار آزاد اعطا میشود؛ با بخشهای تغییرناپذیر «مجوز عمومی همگانی گنو» و «تأمین مالی نرمافزار آزاد»، با متون روی جلد که در (الف) آمده است (زیر را ببینید)، و با متون پشت جلد که در (ب) آمده است (زیر را ببینید). یک نسخه از مجوز در صفحه راهنمای 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.
| 2026-08-10 | gcc-16 |