首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C中神秘的sprintf行为:第二次lld参数打印为0 (0)

C中神秘的sprintf行为:第二次lld参数打印为0 (0)
EN

Stack Overflow用户
提问于 2011-04-15 04:21:59
回答 1查看 1.7K关注 0票数 4

C中的sprintf遇到了一个完全奇怪的问题,这似乎超出了我的基本调试能力。基本上,我使用一个简单的单元测试框架(CuTest)将一些测试添加到一个丑陋的(无文档,没有单元测试)代码库中。我添加了一种新类型的单元测试,它基本上复制了已经存在的单元测试--但是用于代码中使用的64位整数。

这个测试一般有效(正确地评估相等性比较),但是当它失败时,由于sprintf问题,它不会产生正确的错误消息。该函数如下所示:

代码语言:javascript
复制
/* 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,消息如下:

代码语言:javascript
复制
"expected <1> but was <0>"

如果您改变了论点的立场,并使其声明如下:

代码语言:javascript
复制
sprintf(buf, "actually <%lld> but expected <%lld>", actual, expected);

你会得到输出:

代码语言:javascript
复制
"actually <2> but expected <0>"

不用说,这没有什么意义,而且似乎表明了某种奇怪的堆栈错误?老实说,我完全不清楚这种错误是如何发生的--甚至在原则上也是如此。我用CuTest代码做了一个小的工作示例,它正常工作(没有将第二个设置为零)。这表明,问题既不是CuTest,也不是函数本身。

但是,当与实际的代码库一起使用时,它会遇到这个问题。与环境相关的东西(堆栈、内存或变量)是问题所在。

有人知道为什么会发生这种事吗?我目前的候选理论是: 1.在试读数据时,sprintf函数的下溢/溢出。但是,我不确定这是如何发生的,因为传递到函数中的任何数据都是按值传递的。此外,数据本身显然存在--如果我切换顺序,我可以看到每个值。

  1. 我以某种方式使用了不正确的格式。我非常确信lld对于长int是正确的(在我的最小工作示例中也是如此),但它可能是脆弱的。
  2. 对某种类型的堆栈损坏非常感兴趣。希望不是这样,因为我每周只做20个小时的工作。我怀疑我是否能够调试整个代码库来找出如此重要的东西。

我目前正在编译gcc-3在一个cygwin环境中,这是值得的。任何猜测都是很棒的,我知道在没有看到整个代码库的情况下,根本不可能专门诊断它,但是即使是关于调试这类问题的一些线索也是很棒的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-04-15 05:44:01

尝试"%I64d“作为格式字符串。我不确定Cygwin,但我知道来自Visual标准库的printf函数中的MinGW链接,造成了各种各样的破坏。注意任何新的C99特性和类型,如长双或size_t格式。

对于它的价值,这里有一个替代printf在这种情况下:

代码语言:javascript
复制
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);
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5672361

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档