字符空间声明
#include<iostream>
#include<string>
#include <string.h>
using namespace std;
int main(){
char buf[2];
strcpy(buf,"hello world");
cout<<buf<<endl;
}
运行结果为什么是这样?

虽然你的代码中 buf 只有 2 个字节大小,但 strcpy(buf, "hello world") 仍然会强行写入超出 buf 边界的内存,导致缓冲区溢出(Buffer Overflow)。
为什么还能输出 "hello world"?
-
strcpy不会检查目标缓冲区大小strcpy会一直复制字符,直到遇到'\0'(字符串结束符),即使目标缓冲区buf不够大,它也会继续写入相邻的内存空间。
-
cout << buf会一直读取,直到遇到 `'\0'cout会从buf的起始地址开始输出字符,直到遇到'\0'(strcpy会在"hello world"的末尾自动加上'\0')。- 由于
buf溢出,cout会继续读取buf后面的内存,直到碰巧遇到'\0'(可能是未定义的内存区域)。
-
内存布局可能没有立即崩溃
- 在小型程序或某些编译环境下,栈内存可能没有严格的边界检查,所以
strcpy的越界写入可能暂时不会导致程序崩溃。 - 但这是未定义行为(Undefined Behavior, UB),意味着不同编译器、不同运行环境可能会有不同的结果(可能崩溃、输出乱码、或者看似“正常”输出)。
- 在小型程序或某些编译环境下,栈内存可能没有严格的边界检查,所以
实验验证
如果你尝试打印 buf 的地址和附近的内存,可能会发现 "hello world" 被写入了 buf 之外的空间:
#include <iostream>
#include <cstring>
using namespace std;
int main() {
char buf[2];
cout << "buf address: " << (void*)buf << endl;
strcpy(buf, "hello world");
cout << "buf: " << buf << endl; // 可能输出 "hello world",但这是不安全的!
return 0;
}
可能的输出:
buf address: 0x7ffd3a4f8f8e
buf: hello world
但实际上,buf 只申请了 2 字节,后面的内存是被非法写入的。
正确做法
- 使用
strncpy限制复制长度(但仍需手动添加'\0'):char buf[12]; // 足够存放 "hello world" + '\0' strncpy(buf, "hello world", sizeof(buf) - 1); buf[sizeof(buf) - 1] = '\0'; // 确保字符串以 '\0' 结尾 cout << buf << endl; - 使用 C++ 的
std::string(推荐):#include <string> std::string buf = "hello world"; std::cout << buf << std::endl;
总结
strcpy是不安全的,因为它不会检查目标缓冲区大小。- 输出
"hello world"是巧合,实际上程序已经发生了缓冲区溢出,可能导致崩溃或安全漏洞。 - 应该使用更安全的方式(如
strncpy或std::string)来避免此类问题。
浙公网安备 33010602011771号