使用可变参数宏和函数时,“未初始化的值是由堆栈分配创建的”

时间:2013-12-07 09:46:55

标签: c macros variadic-functions variadic-macros

我有以下程序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进行测试

2 个答案:

答案 0 :(得分: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);

答案 1 :(得分:3)

您正在使用%ld打印int类型的常量,并且可能您在intlong的平台上具有相同的大小。它在_itoa_word中发生的事实是一个很好的暗示。

它没有崩溃或打印垃圾的原因是因为读取的额外字节恰好为零,所以读取值的代码得到了正确的值,错误的方式。