【问题标题】:Overlapping memory with sprintf(snprintf)使用 sprintf(snprintf) 重叠内存
【发布时间】:2018-10-26 22:24:38
【问题描述】:

编辑:如果我们有这个呢

char value_arr[8];    
// value_arr is set to some value
snprintf(value_arr, 8, "%d", *value_arr);

这种行为是否已定义?


假设我有一些笨拙的原因

char value_arr[8];
// value_arr is set to some value
int* value_i = reinterpret_cast<int*>(value_arr);

snprintf(value_arr, 8, "%d", *value_i); // the behaviour in question

是否有保证,例如,如果*value_i = 7,那么value_arr 将采用“7”的值。是否定义了这种行为?这样value_i首先被取消引用,然后按值传递,然后格式化,然后存储到数组中。

通常情况下,*value_i 的值预计不会改变,但将字符串存储到 value_arr 会违反这一点。

当我测试它时,它似乎按预期运行,但我似乎无法在文档中找到明确的答案。函数签名有...,据我所知与va_list有关,但恐怕我对可变参数函数的工作方式不是很了解。

int sprintf (char* str, const char* format, ... );

【问题讨论】:

  • 可能是 XY 问题。
  • 可能不是 XY 问题,因为我只是出于好奇。

标签: c++ printf language-lawyer undefined-behavior


【解决方案1】:

对于原始代码,计算表达式 *value_i 会违反严格的别名规则,从而导致未定义的行为。不允许将 char 数组别名为 int

对于编辑后的代码snprintf(value_arr, 8, "%d", *value_arr);,它可以格式化数组中第一个字符的字符代码。函数参数的计算是在进入函数之前排序的。 (C++17 intro.execution/11)

【讨论】:

  • 由于不同的对齐限制,演员表本身不是已经有问题了吗?
  • @Deduplicator 如果未正确对齐,则未指定强制转换结果
  • "函数参数的计算是在进入函数之前排序的。"澄清一下,这只是 C++17 吗?
  • @ChilliDoughnuts 一直都是这样,我只是使用最新的段落编号参考标准。在早期的标准中,参数和后缀表达式之间的顺序不太严格,但函数入口总是有一个顺序点
  • @M.M 好吧,我明白了,所以snprintf(value_arr, 8, "%s othertext", value_arr) 将不会从@Karlinde 的回答中被定义,是吗?因为在这种情况下它会传递指针值。
【解决方案2】:

这是未定义的行为;您使用int* 类型的指针指向char[8] 类型的对象,与int* 相比,它具有不同/宽松的对齐要求。取消引用这个指针然后产生 UB。

【讨论】:

    【解决方案3】:

    可以在https://en.cppreference.com/w/cpp/io/c/fprintf找到以下内容:

    如果对 sprintf 或 snprintf 的调用导致在重叠的对象之间发生复制,则行为未定义。

    根据此页面,我会将您的示例解释为属于这种情况,因此它将被归类为未定义行为。

    编辑:https://linux.die.net/man/3/snprintf 的更多详细信息:

    一些程序不谨慎地依赖如下代码

    sprintf(buf, "%s 一些进一步的文本", buf);

    将文本附加到 buf。但是,标准明确指出,如果在调用 sprintf()、snprintf()、vsprintf() 和 vsnprintf() 时源缓冲区和目标缓冲区重叠,则结果未定义。根据使用的 gcc(1) 版本和使用的编译器选项,上述调用不会产生预期的结果。

    【讨论】:

    • snprintf 的参数在调用之前进行评估,因为它是%d*value_i,所以它是按值调用;所以在我看来没有重叠。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    相关资源
    最近更新 更多