В проекте, над которым я работаю, мы договорились об использовании только функций, возвращающих коды ошибок (без исключений) для обработки ошибок.Прибор по значению аргумента
Для того, чтобы не «загрязнять» мой код сообщениями отладки, я работал над решением, основанным на инструментах (вдохновлен this post).
Вместо того, чтобы использовать Интс как код ошибки, я капсулирования его в классе, как:
// File rc.h
class rc
{
public:
rc(int) __attribute__((no_instrument_function));
rc& operator=(rc);
private:
int value;
};
Затем определения этих операторов и инструментальные функции, как:
// File rc.cc
#include <stdio.h>
#include <time.h>
#include "rc.h"
static FILE *fp_trace;
static int isError;
extern "C"
{
void __attribute__ ((constructor)) trace_begin (void)
{
fp_trace = fopen("trace.out", "w");
isError = 0;
}
void __attribute__ ((destructor)) trace_end (void)
{
if(fp_trace != NULL) {
fclose(fp_trace);
}
}
void __cyg_profile_func_enter (void *func, void *caller) __attribute__((no_instrument_function));
void __cyg_profile_func_exit (void *func, void *caller) __attribute__((no_instrument_function));
void __cyg_profile_func_enter (void *func, void *caller)
{
}
void __cyg_profile_func_exit (void *func, void *caller)
{
if ((fp_trace != NULL) && (isError == 1)) {
fprintf(fp_trace, "x %p %p %lu\n", func, caller, time(NULL));
isError = 0;
}
}
}
rc::rc(int valueIn) :
value(valueIn)
{
}
rc& rc::operator=(rc rcIn)
{
value = rcIn.value;
if (value != 0)
{
isError = 1;
fprintf(fp_trace, "%d\n", value);
}
return *this;
}
Однако в чтобы не печатать слишком много вещей, я не хочу регистрировать вызовы функций, которые возвращают код возврата 0, таким образом, флаг isError
.
Это может быть использовано на следующем примере:
#include <cstdlib>
#include <ctime>
#include "rc.h"
rc bar(void)
{
rc result(std::rand() % 3);
return result;
}
int main(void)
{
std::srand (std::time(NULL));
rc returnCode(0);
for (int i=0; i<10; ++i)
{
returnCode = bar();
}
return 0;
}
компилировать и запускать с
g++ -finstrument-functions -g -c -o rc.o rc.cc
g++ -g -c -o test.o test.cc
g++ test.o rc.o -o a.out
./a.out
Чтение вывода с помощью сценария данной in the previously mentioned post приведет к чему-то вроде:
Error code 2
rc::operator=(rc) at 2016-07-03T18:32:09+0200, called from main (test.cc:32)
Это почти то, что я мог бы пожелать. Но по сравнению с решением, в котором я бы просто добавил тест в rc foo(void)
, чтобы проверить, не является ли вывод ненулевым, а затем зарегистрировать ошибку, которая добавит только служебные данные (плюс накладные расходы из-за проверки) в случае возникновения ошибки (надеюсь, не слишком часто), я собираюсь добавить накладные расходы из-за инструментария (плюс возможные накладные расходы из-за оболочки rc, но я в порядке) при каждом вызове ...
Есть ли решение, Не подумал, что это не повлияло бы на operator=
в случае, когда аргумент равен нулю? Поскольку rc::value
известен только во время выполнения, я не думаю, что шаблон с аргументом имеет значение, которое будет специализировано для value=0
и не будет работать в этом случае. Не так ли?
Существует дополнительное ограничение: важно, чтобы инструментальная функция была оператором присваивания, так как я хочу знать вызывающего, поэтому я не могу добавить дополнительный уровень прокси.
редактировать на этом последнем пункте, я думал о создании встроенный оператор присваивания (а не инструментальными) и вызовите инструментальную функцию в случае код возврата не равен нулю, но это не может работа finstrument-function doc page утверждает, что:
Эта аппаратура также предназначена для функций, расширенных встроенными в другие функции. В запросах профилирования указывается, где, по идее, встроенная функция вводится и выводится.
Так, чтобы он не указывал на настоящего абонента.
Вы знаете, что в любом случае вы, вероятно, закончите с исключениями в вашей программе, если только вы не напишете весь код с нуля и никогда не будете использовать какие-либо библиотеки C++? –
Да, я знаю об этом. Но мы переписываем много вещей ... – Vser
Хорошим советом является использование отрицательных чисел в качестве кодов ошибок и положительных значений для результатов (в том числе 0). Это то, что делает система Linux. –