#c #gcc #gcov
#c #gcc #gcov
Вопрос:
Кто-нибудь может сказать мне, что означает сообщение gcov «Несоответствие слияния для сводок»? Я нашел сообщение в исходном коде gcc здесь:
http://www.opensource.apple.com/source/gcc/gcc-5646/gcc/libgcov.c
Похоже, что теги в .gcda
файлах совпадают для проверки работоспособности, но я не уверен. Кто-нибудь знает, как это обойти?
Ответ №1:
Это происходит, когда один из объектов, которые вы связываете с исполняемым файлом, существенно изменяется. Например, оно увеличивает или теряет некоторые строки профилируемого кода.
Минимальный случай возникновения ошибки связан с двумя исходными файлами. Вот 2 примера исходных файлов с именем main.c…
/* main.c */
int do_stuff(int value);
int main(int argc, const char *argv[])
{
do_stuff(argc);
return 0;
}
и прочее.c
/* stuff.c */
#include <stdio.h>
#if 0
int more_stuff()
{
int i;
i = 0;
return i;
}
#endif
int do_stuff(int value)
{
if (value > 1) {
printf("Value > 1n");
} else {
printf("Value <= 1n");
}
return 0;
}
То, что они делают, не важно. Для их сборки вот простой Makefile:
CFLAGS := -fprofile-arcs -ftest-coverage
LDFLAGS := -fprofile-arcs -ftest-coverage
testexe: main.o stuff.o
$(CC) $(LDFLAGS) -o $@ $^
Makefile настроен так, что компиляция является main.c -> main.o
, stuff.c -> stuff.o
и, наконец stuff.o main.o -> testexe
, завершенной. Если мы скомпилируем и свяжем эти файлы C с -fprofile-arcs -ftest-coverage
параметрами, то исполняемый файл будет иметь профилирование. Запустите этот исполняемый файл, и вы получите 2 выходных файла, main.gcda
и stuff.gcda
. Пока все хорошо.
Теперь измените строку #if 0
на #if 1
. Makefile должен привести к перекомпиляции just stuff.c и повторной компоновке исполняемого файла. При следующем запуске тестового исполняемого файла вы получите сообщение «Несоответствие слияния» для основного файла.gcda. Файл stuff.gcda не затронут, поскольку его объектный файл был воссоздан со всей новой сводной информацией. Если вы перекомпилируете main.c
и повторно свяжете исполняемый файл, сообщение об ошибке исчезнет.
Итак, что можно сделать? Я хотел бы знать! На данный момент я запускаю find . -name '*.gcda' | xargs rm
всякий раз, когда мне нужно перепроверить покрытие, что на самом деле не идеально. Другим решением было бы перекомпилировать все при использовании профилирования «на всякий случай», но это кажется излишеством.
Комментарии:
1. Отлично, спасибо за информацию! Приятно наконец понять, что здесь происходит. Также отличное объяснение. У меня был аналогичный обходной путь — удалить все сгенерированные файлы перед запуском. Теперь я понимаю, почему это работает, но я думаю, что сообщение об ошибке можно было бы несколько улучшить.