【问题标题】:strcpy and string presentation in memory内存中的 strcpy 和字符串表示
【发布时间】:2014-05-28 11:53:37
【问题描述】:

我有一个这样的程序(x86_64 GNU/Linux)

int main()
{
    char s[] = "123456789";
    char d[] = "123";
    strcpy(d, s);

    printf("%p, %0p\n", s, d);
    printf("%s, %s", s, d);

    return 0;
}

输出是:0xeb6d2930 0xeb6d2910 123456789 123456789 我对结果有点困惑 我觉得内存中的程序是这样的:

  • '9','\0' 。 .
  • '5','6','7','8'
  • 0x7fff813af310: '1','2','3','4'
  • 0x7fff813af300: '1','2','3','\0'

所以结果应该是 *s = "789", *d = "123456789"

你们能解释一下为什么结果不像我想的那样吗? 我将格式说明符更改为 %p 以打印 d 和 s 的地址 我知道 s 和 d 重叠所以没有足够的空间 d 持有 s 可能导致未定义的行为,但无论如何我想知道 为什么结果是 *s = "123456789" *d = "123456789"

【问题讨论】:

  • strcpy(d, s); BANGd 中没有空格,用于所有s。您的程序受到Undefined Behaviour 的影响。
  • 啊,是的,每天的“我正在将内容复制到一个没有指向足够有效内存的指针中”的问题。

标签: c printf undefined-behavior buffer-overflow strcpy


【解决方案1】:

从您显示的地址布局的输出中,它的初始内容似乎是:

       offset 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f  
d: 0xeb6d2910 30 31 32 00 xx xx xx xx xx xx xx xx xx xx xx xx | 1 2 3 . . . . . . . . . . . . .
   0xeb6d2920 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx | . . . . . . . . . . . . . . . .
s: 0xeb6d2930 30 31 32 33 34 35 36 37 38 39 00 xx xx xx xx xx | 1 2 3 4 5 6 7 8 9 . . . . . . . 

strcpy(d, s)之后:

       offset 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f  
d: 0xeb6d2910 30 31 32 33 34 35 36 37 38 39 00 xx xx xx xx xx | 1 2 3 4 5 6 7 8 9 . . . . . . . 
   0xeb6d2920 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx | . . . . . . . . . . . . . . . .
s: 0xeb6d2930 30 31 32 33 34 35 36 37 38 39 00 xx xx xx xx xx | 1 2 3 4 5 6 7 8 9 . . . . . . . 

但是,对于d,分配的内存较少,因为在strcpy() 期间使用的代码会调用 undefeind 行为。

【讨论】:

    【解决方案2】:

    您的程序在这两个方面有未定义的行为:

    • strcpy() 的缓冲区溢出:请勿写入不属于您的内存。
    • printf() 的格式说明符错误:使用 %p 打印指针地址。但仅适用于数据指针。

    请为main 使用正确的原型,你几乎拥有它(这可能是UB,虽然我没有遵循所有的论点):

    int main(void)
    int main(int argc, char* argv[])
    

    或兼容或实现定义的扩展是有效的。

    未定义的行为意味着一切正常,甚至是鼻恶魔。

    【讨论】:

      【解决方案3】:

      您的程序调用未定义的行为,因为:
      1.d没有足够的空间来容纳大于4字节的字符串(包括\0)。
      2. 您使用了错误的格式说明符来打印地址。

      结果是预期的或意外的。

      【讨论】:

        猜你喜欢
        • 2014-10-01
        • 2014-06-17
        • 1970-01-01
        • 2011-04-23
        • 2019-03-13
        • 1970-01-01
        • 2016-03-16
        • 2021-03-28
        • 2011-07-04
        相关资源
        最近更新 更多