二维动态数组扩展失败:调用expand函数后抛出异常
问题分析与修复
你的代码抛出异常主要有两个核心问题,还有一个输入处理的小问题,逐一说明:
核心问题1:新扩展的数组元素未初始化
expand函数中,新分配的temparr只复制了原数组中已有的noofelements个元素,从noofelements到新rows-1的位置都是未初始化的野指针。当调用expand后,你立刻尝试用cin.getline写入arr[noofelements](也就是新数组中未初始化的位置),这会访问非法内存,直接触发异常。
核心问题2:rows参数未按引用传递
expand函数中的rows是按值传递的,函数内对rows的修改不会同步到main函数的rows变量。这会导致main里的条件判断noofelements < rows永远用旧的rows值(初始5),逻辑彻底混乱——比如第一次扩展后noofelements变成5,rows还是5,会再次进入else分支重复调用expand,加剧野指针问题。
输入处理小问题:cin缓冲区残留换行符
用户输入字符串后按下回车,换行符会留在输入缓冲区,下一次cin.getline会直接读取这个换行符作为空字符串,导致noofelements错误递增,可能提前触发扩展逻辑。
修复后的代码
#include<iostream> #include<limits> // 用于numeric_limits using namespace std; // rows改为引用传递,同步更新main中的rows值 void expand(char**& arr, int& rows, int noofelements) { int newRows = rows + 5; char** temparr = new char*[newRows]; // 复制原有元素 for (int i = 0; i < noofelements; i++) { temparr[i] = arr[i]; } // 初始化新扩展的元素,分配内存 for (int i = noofelements; i < newRows; i++) { temparr[i] = new char[50]; } delete[] arr; arr = temparr; rows = newRows; // 更新rows的值 cout << "******\narray was expanded\n*****\n"; } int main() { char** arr; int rows = 5, noofelements = 0; arr = new char*[rows]; for (int i = 0; i < rows; i++) { arr[i] = new char[50]; } while (1) { if (noofelements < rows) { cout << "enter string\n"; // 先忽略缓冲区中的换行符,避免读取空字符串 if (noofelements > 0) { cin.ignore(numeric_limits<streamsize>::max(), '\n'); } cin.getline(arr[noofelements++], 50); } else { expand(arr, rows, noofelements); cout << "enter string\n"; cin.ignore(numeric_limits<streamsize>::max(), '\n'); cin.getline(arr[noofelements++], 50); } } // 实际使用中需在退出循环时释放内存,避免泄漏 for (int i = 0; i < rows; i++) { delete[] arr[i]; } delete[] arr; return 0; }
关键修复点说明
- rows改为引用传递:
void expand(char**& arr, int& rows, int noofelements),确保函数内对rows的修改同步到main函数。 - 初始化新扩展的元素:在
expand中新增循环,为新分配的数组位置逐一分配char数组内存,避免野指针。 - 处理输入缓冲区:使用
cin.ignore清除输入缓冲区中的残留换行符,确保每次getline都能正确读取用户输入的字符串。 - 添加内存释放逻辑:虽然是死循环,但实际代码中应该在退出时释放所有动态分配的内存,避免内存泄漏。
内容的提问来源于stack exchange,提问作者GA Haroon
相关产品推荐
相关产品推荐

