我一直在测试 malloc() 和各种字符串函数之间的交互,以便尝试更多地了解指针和内存在 C 中的工作原理,但我对以下交互有点困惑。
char *myString = malloc(5); // enough space for 5 characters (no '\0')
strcpy(myString, "Hello"); // shouldn't work since there isn't enough heap memory
printf(%s, %zd\n", myString, strlen(myString)); // also shouldn't work without '\0'
free(myString);
上面的一切似乎都工作正常。我尝试对每个字符使用 printf() 来查看是否存在空终止符,但“\0”似乎只是打印为空格。
我的困惑在于:
- 字符串文字总是有一个隐式的空终止符。
- strcpy 应该将 null 终止符复制到 myString 上,但没有足够的分配堆内存
- 除非 myString 有终止符,否则 printf/strlen 不应该工作
既然 myString 显然有一个空终止符,那么它在哪里?它只是被放置在随机的内存位置吗?上面的代码是不是一个等待发生的错误?
最佳答案
解决你的三点:
- 字符串文字始终具有隐式 null 终止符。
正确。
- strcpy 应该将 null 终止符复制到 myString 上,但没有足够的分配堆内存
strcpy
无法知道目标缓冲区有多大,并且会很高兴地写入超过其末尾的内容(覆盖内存中缓冲区后面的任何内容。有关此关闭的信息 -终端访问查找“缓冲区溢出”或“缓冲区溢出”。这些是常见的安全弱点)。
对于更安全的版本,请使用 strncpy
,它将目标缓冲区的长度作为参数,以免写入超过其末尾。
- 除非 myString 有终止符,否则 printf/strlen 不应该工作
“不应该工作”这个短语在这里有点含糊。 printf/strlen/etc 将继续读取内存,直到找到空终止符,该终止符可能紧接在字符串之后,也可能位于数千字节之外(在您的情况下,您已将空终止符立即写入 myString 之后的内存,因此 printf/strlen/etc 将停在那里)。
最后:
- 上面的代码是一个等待发生的错误吗?
是的。您正在覆盖尚未分配的内存,这可能会导致各种问题,具体取决于被覆盖的内容。
从 strcpy
手册页:
If the destination string of a strcpy() is not large enough, then anything might happen. Overflowing fixed-length string buffers is a favorite cracker technique for taking complete control of the machine. Any time a program reads or copies data into a buffer, the program first needs to check that there's enough space. This may be unnecessary if you can show that overflow is impossible, but be careful: programs can get changed over time, in ways that may make the impossible possible.
关于c - malloc 和 strcpy 交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47783233/