C中的sprintf遇到了一个完全奇怪的问题,这似乎超出了我的基本调试能力。基本上,我使用一个简单的单元测试框架(CuTest)将一些测试添加到一个丑陋的(无文档,没有单元测试)代码库中。我添加了一种新类型的单元测试,它基本上复制了已经存在的单元测试--但是用于代码中使用的64位整数。
这个测试一般有效(正确地评估相等性比较),但是当它失败时,由于sprintf问题,它不会产生正确的错误消息。该函数如下所示:
/* Comparison Function for U64 Numbers */
void CuAssertU64Equals_LineMsg(CuTest* tc, const char* file, int line, const char* message, u64 expected, u64 actual) {
char buf[STRING_MAX];
if (expected == actual) return;
sprintf(buf, "expected <%lld> but was <%lld>", expected, actual);
CuFail_Line(tc, file, line, message, buf);
}(注意: STRING_MAX是512,所以应该很大)。(注2:在我目前正在使用的Cygwin系统上,u64是一个“长int”变量)
当测试失败时,产生的错误消息是奇怪的部分。不管“实际”的值是什么,它都会在那个位置打印0。因此,给定预期=1和实际= 2,消息如下:
"expected <1> but was <0>"如果您改变了论点的立场,并使其声明如下:
sprintf(buf, "actually <%lld> but expected <%lld>", actual, expected);你会得到输出:
"actually <2> but expected <0>"不用说,这没有什么意义,而且似乎表明了某种奇怪的堆栈错误?老实说,我完全不清楚这种错误是如何发生的--甚至在原则上也是如此。我用CuTest代码做了一个小的工作示例,它正常工作(没有将第二个设置为零)。这表明,问题既不是CuTest,也不是函数本身。
但是,当与实际的代码库一起使用时,它会遇到这个问题。与环境相关的东西(堆栈、内存或变量)是问题所在。
有人知道为什么会发生这种事吗?我目前的候选理论是: 1.在试读数据时,sprintf函数的下溢/溢出。但是,我不确定这是如何发生的,因为传递到函数中的任何数据都是按值传递的。此外,数据本身显然存在--如果我切换顺序,我可以看到每个值。
我目前正在编译gcc-3在一个cygwin环境中,这是值得的。任何猜测都是很棒的,我知道在没有看到整个代码库的情况下,根本不可能专门诊断它,但是即使是关于调试这类问题的一些线索也是很棒的。
发布于 2011-04-15 05:44:01
尝试"%I64d“作为格式字符串。我不确定Cygwin,但我知道来自Visual标准库的printf函数中的MinGW链接,造成了各种各样的破坏。注意任何新的C99特性和类型,如长双或size_t格式。
对于它的价值,这里有一个替代printf在这种情况下:
static char *CuPrintU64(char* buffer, u64 value) {
do
*--buffer = value % 10 + '0';
while(value /= 10);
return buffer;
}
/* Comparison Function for U64 Numbers */
void CuAssertU64Equals_LineMsg(CuTest* tc, const char* file, int line, const char* message, u64 expected, u64 actual) {
static const char first[] = "expected ";
static const char second[] = " but was ";
char buf[STRING_MAX], *ptr = &buf[sizeof buf];
if(expected == actual) return;
/* sprintf(buf, "expected <%llu> but was <%llu>", expected, actual); */
*--ptr = '\0';
ptr = CuPrintU64(ptr, actual);
ptr = memcpy(ptr - second, sizeof second - 1);
ptr = CuPrintU64(ptr, expected);
ptr = memcpy(ptr - first, sizeof first - 1);
CuFail_Line(tc, file, line, message, ptr);
}https://stackoverflow.com/questions/5672361
复制相似问题