Отслеживание вызовов функций - PullRequest
0 голосов
/ 21 декабря 2010

Я хотел бы регистрировать вызовы функций, сделанные во время выполнения программы на Си. Идея состоит в том, чтобы создать историю вызовов функций. Я хочу это, чтобы я мог программно проверить, что тестовые фальшивые функции были вызваны. Меня не волнуют аргументы или возвращаемые значения. В идеале я бы хотел, чтобы это выглядело примерно так:

long longfunc0();
void voidfunc2(char arg0, char arg1);

typedef void (*varargs_funcptr)(...);
void test1()
{
    varargs_funcptr function_calls[10];
    function_calls[0] = longfunc0;
    function_calls[1] = voidfunc2;
    assert(function_calls[0] == longfunc0);
}

Можно ли сделать typedef, чтобы мне не нужно было явно приводить к varargs_funcptr?

Ответы [ 4 ]

1 голос
/ 21 декабря 2010

Если вы регистрируете только те функции, которые выполнялись, и вы не будете использовать эти указатели позже, может быть проще привести указатель функции к целому числу без знака (соответствующей длины для вашей архитектуры).Вы все еще можете «распечатать» все указатели в конце программы в виде шестнадцатеричных адресов, и не имеет значения, какой тип аргумента или количество.

Проблема в том, что ваши функции могут ненаходиться по одинаковым адресам памяти при каждом запуске программы.Это затрудняет выяснение, какая функция идет с каким указателем.Это потребует больше памяти, но вам может повезти, если вы сохраните строковое представление имени функции.

0 голосов
/ 21 декабря 2010

Спасибо bta за указание в правильном направлении. Вместо использования целых чисел я использую пустые указатели, но решение по сути то же самое. Единственное, что мне не нравится в этом решении, - это явное приведение.

void test1()
{
    void * function_calls[10];
    function_calls[0] = (void *)longfunc0;
    function_calls[0] = (void *)voidfunc2;
    assert(function_calls[0] == ((void *)voidfunc2));
}
0 голосов
/ 21 декабря 2010

Самый простой способ войти в C - это использовать функции, определенные в syslog.h (если вы в системе Unix):

 void closelog(void);

 void openlog(const char *ident, int logopt, int facility);

 int setlogmask(int maskpri);

 void syslog(int priority, const char *message, ...);

 void vsyslog(int priority, const char *message, va_list args);

Когда вы используете эти функции, он напрямую записывает ваш журнал в системный журнал сообщений (например, /var/log/myapplication.log).

Этот файл также определяет много уровней журнала:

LOG_EMERG Состояние паники. Обычно это транслируется всем пользователям.

LOG_ALERT Условие, которое следует немедленно исправить, например, поврежденная системная база данных.

LOG_CRIT Критические условия, например, ошибки жесткого устройства.

LOG_ERR Ошибки.

LOG_WARNING Предупреждающие сообщения.

LOG_NOTICE Условия, которые не являются условиями ошибки, но, возможно, должны обрабатываться специально.

LOG_INFO Информационные сообщения.

LOG_DEBUG Сообщения, которые содержат информацию, обычно используемую только при отладке программы.

Например, если вы хотите войти с помощью syslog, вы можете попробовать это:

/ * Второй параметр означает, что соединение с системным журналом откроется немедленно и вы распечатаете удостоверение личности процесса. * /

openlog ("syslogd", LOG_NDELAY | LOG_PID, LOG_SYSLOG);

syslog (LOG_INFO, "Некоторая строка blalblabla");

closelog (); * * одна тысяча тридцать семь

0 голосов
/ 21 декабря 2010

я не знаю, почему вы пытаетесь усложнить свою жизнь

, если вы просто пытаетесь сделать небольшой проект, добавьте функцию регистрации:

#if defined(LOGGING)
#define LOG(s) log(s)
#else
#define LOG(s)
#endif

void log(char *s){
    printf("%s");
    return;
}

void test1()
{
    log("test1()\n");

    return;
}

не уверен, что это работаетили нет мелких ошибок, но вы поняли

...