自制模板Matrix类触发SIGSEGV错误,请求技术排查指导
嘿,我来帮你一步步揪出导致段错误的元凶,先从几个最直接的问题说起:
1. 最致命的越界访问:selectedTab超出矩阵列范围
看你的MenUI构造函数:
MenUI::MenUI():selectedTab(3),selectedItem(4),menItems(matrix<string>(3,4)) {
你实例化的menItems是3列4行的矩阵(matrix构造函数第一个参数是列数),所以列的有效索引是0、1、2,但你把selectedTab初始化为3——这直接超出了列的合法范围!在print函数里执行menItems[selectedTab][i]时,相当于访问tabs[3],而tabs数组只有3个元素,这必然触发段错误。
2. Matrix析构函数的数组释放错误
你的matrix类析构函数写的是:
virtual ~matrix() { delete tabs; }
但tabs是用new vektor<T>[columns]分配的数组,释放数组必须用delete[],而不是delete。用错释放方式会导致内存泄漏和未定义行为,这也是段错误的常见诱因,赶紧改成:
virtual ~matrix() { delete[] tabs; }
3. 拷贝构造和赋值运算符的致命逻辑错误
你的拷贝构造函数和operator=都把数组指针当成单个对象处理了,这会直接导致内存越界:
- 拷贝构造函数里,不仅写错了成员变量名(
matrix类没有rows成员,应该是columns),还错误地用new vektor<T>(*other.getTabs())构造了单个vektor对象,而不是数组。后续访问tabs[index]时,本质是在单个对象的内存后面越界读写,必然崩溃。 - 赋值运算符里还多了个拼写错误:
spalten = rhs.getColCount();——matrix类的成员是columns,不是spalten。
正确的拷贝构造函数应该循环创建每个列的vektor:
matrix(const matrix& other):columns(other.getColCount()),tabs(new vektor<T>[columns]) { for(int i = 0; i < columns; ++i) { tabs[i] = other.tabs[i]; } }
正确的赋值运算符要先释放原有内存,再循环拷贝:
matrix<T>& operator=(const matrix& rhs) { if (this == &rhs) return *this; // 处理自赋值,避免重复释放 // 先释放当前对象的内存 delete[] tabs; columns = rhs.getColCount(); tabs = new vektor<T>[columns]; for(int i = 0; i < columns; ++i) { tabs[i] = rhs.tabs[i]; } return *this; }
4. Vektor类operator[]的const正确性问题
你的vektor类的operator[]是const成员函数,但返回的是非const引用:
T& operator[](const unsigned int index)const { if(index >= 0 && index < length) { return items[index]; } else throw out_of_bounds(); }
在const成员函数里,items会被视为const T*,你不能返回T&(非const引用),这会导致编译错误(如果现在没报错可能是编译器宽松模式)。应该提供两个版本的operator[]:
// 非const版本:允许修改元素 T& operator[](unsigned int index) { if(index >= length) { // unsigned int 不可能小于0,无需判断>=0 throw out_of_bounds(); } return items[index]; } // const版本:只读访问const对象的元素 const T& operator[](unsigned int index) const { if(index >= length) { throw out_of_bounds(); } return items[index]; }
5. Matrix构造函数的内存泄漏
在matrix(int columns, int rows)构造函数里:
for(int i = 0; i< columns;i++) { tabs[i] = *new vektor<T>(rows); }
这里new vektor<T>(rows)创建的临时对象,赋值给tabs[i]后就没人管了,会导致内存泄漏。其实不需要用new,直接赋值临时对象即可:
for(int i = 0; i< columns;i++) { tabs[i] = vektor<T>(rows); }
额外的边界问题:selectedItem也越界了
你的menItems是4行(索引0-3),但selectedItem初始化为4,在print函数里i == selectedItem时,访问menItems[selectedTab][4]也会越界,记得把selectedItem改成0-3之间的值。
把这些问题逐一修复后,你的SIGSEGV错误应该就能解决了。
内容的提问来源于stack exchange,提问作者Raphael

