2

我有以下程序http://ideone.com/1RPs8E。它使用可变参数函数 tlog 来打印日志文件中的一行。它接收打印行的级别、文件名、行和用于调试信息的函数以及 printf 的格式和参数列表。

void tlog(int level, const char *file, int line, const char *fun, const char *fmt, ...)

我还使用了一个 LOGL 宏,它为当前文件、行和函数调用 tlog 函数。

#define LOGL(level, fmt, ...) tlog(level, __FILENAME__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)

以及使用 LOGL 宏的各种宏,例如:

#define DEBUGEX(fmt, ...) LOGL(LDEBUGEX, fmt, ##__VA_ARGS__)
#define DEBUG(fmt, ...) LOGL(LDEBUG, fmt, ##__VA_ARGS__)
#define INFO(fmt, ...)  LOGL(LINFO, fmt, ##__VA_ARGS__)

在 valgrind 中运行程序时:

$ valgrind -v --track-origins=yes ./t

我收到以下错误:第 150 行的“未初始化的值是由堆栈分配创建的”(当我使用 DEBUGEX 宏时)。完整日志在这里: http: //pastebin.com/rZu4nkHd

代码有什么问题?对我来说似乎没问题。如果我从 tlog 函数和所有调用它的宏中删除 level 参数,则不再发生错误。

在 Archlinux 上使用 gcc 4.8.2 测试,在 Ubuntu 12.04.3 上使用 gcc 4.6.3 测试

4

2 回答 2

4
#define nmemb 1
#define size 32

...
void *_nptr_ = calloc((nmemb), (size));
LOGL(LDEBUGEX, "CALLOC: %#lX nmemb %ld, size %ld", _nptr_, (nmemb), (size));

转换说明符都是错误的三个。

后两个转换说明符会导致 Valgrind 抱怨,因为 () 中传递的数据量int与格式期望的 () 不匹配long

格式应如下所示:

..., "%p ... %d ... %d", _nptr_, ...

然而,“更好”的方法是:

#define nmemb ((size_t) 1)
#define size ((size_t) 32)

...

..., "%p ... %zu ... %zu", _nptr_, nmemb, size);
于 2013-12-07T10:17:15.130 回答
3

%ld用于打印 type 的常量int,并且大概您在那里的平台上int并且long没有相同的大小。它发生的事实_itoa_word是一个很好的暗示。

它不会崩溃或打印垃圾的原因是因为读取的额外字节恰好为零,因此读取值的代码会以错误的方式获得正确的值。

于 2013-12-07T10:17:05.697 回答