未初始化变量的 C++ 内存分配(32 位机器)

C++ Memory Allocation Of A Variable That Is Not Initialized (32bit Machine)

我注意到如果你在这样的函数内部分配一个 char array

void example()
{
    char dataBuffer[100] = { 0 };
}

然后用 IDA 检查函数的反汇编,这实际上插入了对 memset() 的调用以初始化 char array。我把它反转后看起来像这样

memset(stackPointer + offset + 1, 0, 100);

原始程序集看起来像

addic     r3, r1, 0x220
addic     r3, r3, 1
clrldi    r3, r3, 32
li        r4, 0
li        r5, 0x64
bl        memset

但是如果我将 example() 函数更改为

void example()
{
    char dataBuffer[100];
}

然后我在 IDA 中检查反汇编时注意到没有插入对 memset() 的调用。 所以基本上我的问题是,如果 char array 没有初始化为零,它仍然可以安全使用吗?例如

void example()
{
    char dataBuffer[100];
    strcpy(dataBuffer, "Just some random text");
    strcat(dataBuffer, "blah blah blah example text[=14=]");//null terminator probably not required as strcpy() appends null terminator and strcat() moves the null terminator to end of string. but whatever
}

当 writing/reading 到 char array 时,我是否应该期待任何 UB,即使它没有初始化为零,插入的 memset() 随附用 = { 0 } 初始化 char 数组?

将其作为包含垃圾数据的数组来处理是绝对安全的。这意味着 写入 是安全的,读取 是不安全的。你只是还不知道里面有什么。函数 strcpy 不从它获取的数组中读取(或者更具体地说,从它获取的指针中读取)它只是写入它。所以很安全。

完成写入字符缓冲区后。当你开始使用它时,你将经历它直到你遇到一个空(0)字符。当您最后写入时,该空字符将设置在那里。如果你没有初始化它,空字符之后就是垃圾,如果你做了,它就会变成 0。在这两种情况下,都没关系,因为您不会读取空字符。

参见:http://www.cplusplus.com/reference/cstring/strcpy/

它使用了与您提供的代码非常相似的示例。

char dataBuffer[100];

调用变量 dataBuffer 存在,因此也将内存与之相关联。但是,作为优化,此内存未初始化。 C 旨在不执行任何不必要的工作,而您在此处使用 C++ 的 C 子集。

也就是说,如果您的编译器可以证明您实际上没有使用内存,则不需要分配它。但是根据定义,从您的 运行ning 标准兼容代码中无法检测到这种优化。您的代码将 运行 就好像 内存已分配。 (此 as-if 规则是允许您的编译器执行的几乎所有优化的基础。)

您的 strcpy()strcat() 调用没有问题,因为它们没有超过 运行 分配的缓冲区。但最好忘记 strcpy()strcat() 存在,现在有更好、更安全的功能可以使用。