未初始化变量的 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()
存在,现在有更好、更安全的功能可以使用。
我注意到如果你在这样的函数内部分配一个 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()
存在,现在有更好、更安全的功能可以使用。