字符空间声明

#include<iostream>
#include<string>
#include <string.h>
using namespace std;
int main(){
	char buf[2];
	strcpy(buf,"hello world");
	cout<<buf<<endl; 
} 

运行结果为什么是这样?
image
虽然你的代码中 buf 只有 2 个字节大小,但 strcpy(buf, "hello world") 仍然会强行写入超出 buf 边界的内存,导致缓冲区溢出(Buffer Overflow)

为什么还能输出 "hello world"?

  1. strcpy 不会检查目标缓冲区大小

    • strcpy 会一直复制字符,直到遇到 '\0'(字符串结束符),即使目标缓冲区 buf 不够大,它也会继续写入相邻的内存空间。
  2. cout << buf 会一直读取,直到遇到 `'\0'

    • cout 会从 buf 的起始地址开始输出字符,直到遇到 '\0'strcpy 会在 "hello world" 的末尾自动加上 '\0')。
    • 由于 buf 溢出,cout 会继续读取 buf 后面的内存,直到碰巧遇到 '\0'(可能是未定义的内存区域)。
  3. 内存布局可能没有立即崩溃

    • 在小型程序或某些编译环境下,栈内存可能没有严格的边界检查,所以 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 字节,后面的内存是被非法写入的。


正确做法

  1. 使用 strncpy 限制复制长度(但仍需手动添加 '\0'):
    char buf[12]; // 足够存放 "hello world" + '\0'
    strncpy(buf, "hello world", sizeof(buf) - 1);
    buf[sizeof(buf) - 1] = '\0'; // 确保字符串以 '\0' 结尾
    cout << buf << endl;
    
  2. 使用 C++ 的 std::string(推荐)
    #include <string>
    std::string buf = "hello world";
    std::cout << buf << std::endl;
    

总结

  • strcpy 是不安全的,因为它不会检查目标缓冲区大小。
  • 输出 "hello world" 是巧合,实际上程序已经发生了缓冲区溢出,可能导致崩溃或安全漏洞。
  • 应该使用更安全的方式(如 strncpystd::string)来避免此类问题。
posted @ 2025-06-30 16:03  f-52Hertz  阅读(11)  评论(0)    收藏  举报