gpt4 book ai didi

c - C 中神秘的 sprintf 行为 : Second lld param prints as zero (0) always

转载 作者:行者123 更新时间:2023-12-01 17:18:57 25 4
gpt4 key购买 nike

我在 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是一个“long long int”变量)

当这个测试失败时,产生的错误消息是奇怪的部分。无论“actual”的值是多少,它都会在该位置打印 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 函数出现下溢/上溢。我不确定这是如何发生的,因为传递到函数中的任何数据都是按值传递的。此外,数据本身显然存在 - 如果我切换顺序,我可以看到每个值。

  1. 我使用了不正确的格式。我很确定 lld 对于 long long int 是正确的(并且在我的最小工作示例中有效),但也许它很脆弱。

  2. 某种类型的堆栈完全损坏。当然希望不是这样,因为我每周只花 20 个小时在这个项目上。我怀疑我是否可以调试整个代码库来找出如此重要的东西。

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

最佳答案

尝试使用“%I64d”作为格式字符串。我不确定 Cygwin,但我知道 Visual Studio 标准库的 printf 函数中的 MinGW 链接,导致了各种破坏。请注意任何新的 C99 功能和类型,例如长 double 或 size_t 格式。

就其值(value)而言,这里是 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);
}

关于c - C 中神秘的 sprintf 行为 : Second lld param prints as zero (0) always,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5672361/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com