我有以下程序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进行测试
答案 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
类型的常量,并且可能您在int
和long
的平台上具有相同的大小。它在_itoa_word
中发生的事实是一个很好的暗示。
它没有崩溃或打印垃圾的原因是因为读取的额外字节恰好为零,所以读取值的代码得到了正确的值,错误的方式。