为何容量为30的char数组输出长度为38?C++数组越界问题咨询
为什么C++数组溢出时编译器没有立即报错?
先来看你的代码:
#include <iostream> #include <vector> #include <string> #include <cstring> using namespace std; int main() { //initialising the char array and vector char sentence[30] = {}; vector<string> words{"The", "only", "thing", "to", "fear", "is", "fear", "itself"}; //For loop iterates through the vector and adds the converted strings to the char array for(int i = 0; i < words.size(); i++){ //if statements check if there is overflow and breaks the loop if there is /*if(strlen(sentence) >= 30){ cout << "stop" << endl;//comment out later break; }*/ //strcat method adds the strings from words to sentence one at a time strcat(sentence, words[i].c_str()); /*if(strlen(sentence) >= 30){ cout << "stop" << endl;//comment out later break; }*/ //strcat method adds a space in between each word in the cstring strcat(sentence, " "); } //couts the full sentence and the length of sentence cout << sentence << " " << strlen(sentence) << endl; cout << sentence[29] << endl; return 0; }
你的核心疑问其实是C++语言本身的特性导致的,不是代码逻辑的“错误”(当然代码存在内存不安全的问题),下面具体解释:
1. C++的「信任程序员」设计逻辑
C++继承了C的设计理念:优先保证性能,默认不会做运行时数组边界检查。这类检查会额外增加计算开销,语言标准假设程序员会自己把控内存访问的安全性。
当你用strcat往sentence里写入超过30字节的内容时,这属于未定义行为(Undefined Behavior)。未定义行为的意思是:C++标准不强制要求程序此时必须报错、崩溃或做任何特定操作——它可能看起来“正常运行”,可能输出乱码,可能在后续操作中突然崩溃,甚至在不同编译器/操作系统下表现完全不同。
2. 为什么编译器没提前警告?
默认情况下,大多数编译器不会主动检测这类潜在的越界写入问题,因为这类检查需要复杂的静态分析(比如在编译时预测strcat的调用会导致溢出)。不过你可以通过开启编译器的警告选项来获得提示:
- 对于GCC/Clang,编译时加上
-Wall -Wextra选项,会触发关于潜在内存不安全的警告; - 如果你想在运行时精准检测这类问题,可以使用地址 sanitizer,编译时加上
-fsanitize=address,程序运行时会直接报错并指出越界的具体位置。
3. 更适合新手的安全写法
作为C新手,建议尽量避免使用C风格数组和strcat、strlen这类不安全的C标准库函数,改用C标准库的std::string——它会自动管理内存,完全不用你手动处理数组大小的问题:
#include <iostream> #include <vector> #include <string> using namespace std; int main() { string sentence; vector<string> words{"The", "only", "thing", "to", "fear", "is", "fear", "itself"}; for(const auto& word : words){ sentence += word; sentence += " "; } cout << sentence << " " << sentence.size() << endl; // 使用at()方法访问元素,越界时会抛出明确的异常 if(sentence.size() > 29){ cout << sentence.at(29) << endl; } return 0; }
这样代码更简洁,还能彻底避免数组溢出的风险,而且std::string::at()方法会在访问越界元素时抛出std::out_of_range异常,帮你及时定位问题。
内容的提问来源于stack exchange,提问作者Charles Simmons
相关产品推荐
相关产品推荐

