使用delete[]无法正确释放Matrix类动态数组,触发断言失败
使用delete[]无法正确释放Matrix类动态数组,触发断言失败
兄弟,你的问题根源是对delete[]的一个非常常见的误解——C++里调用delete[]释放内存后,根本不会自动把原指针置为NULL!你那些断言之所以失败,完全是因为这个错误的假设。
咱们一点点拆解问题:
- 当你执行
delete[] matrixM[i];时,只是把这块内存还给了操作系统,但matrixM[i]这个指针本身的值还是原来的内存地址(现在变成了野指针,指向的内存已经无效),所以你紧接着断言matrixM[i] == NULL,肯定会触发失败,因为指针值根本没被修改。 - 更离谱的是你
delete[] matrixM;之后居然断言matrixM != NULL——这逻辑完全反了,虽然这个断言不会触发失败(因为指针还是原来的地址),但它没有任何意义,你都已经释放了matrixM的内存,这个指针已经是野指针了,检查它是不是NULL毫无价值。 - 同理,
sum_rowsM和sum_colsM的断言也是错的,delete[]后它们的指针值也不会自动变成NULL。
那该怎么修正呢?有两种思路:
思路1:去掉错误的断言(推荐)
其实delete[]执行成功的标志不是指针变成NULL,而是你确实对每一块用new[]分配的内存都调用了对应的delete[]。这些断言不仅没用,还会误导你觉得释放失败了。修正后的代码:
void Matrix::destroy() { for(int i=0; i < rowsM; i++){ delete[] matrixM[i]; } delete[] matrixM; delete[] sum_rowsM; delete[] sum_colsM; }
思路2:手动置空指针后再断言(如果非要保留断言)
如果你确实想通过断言验证,那必须手动把指针赋值为NULL,因为C++不会帮你做这件事。修正后代码:
void Matrix::destroy() { for(int i=0; i < rowsM; i++){ delete[] matrixM[i]; matrixM[i] = NULL; // 手动置空 assert(matrixM[i] == NULL); // 现在断言会成功 } delete[] matrixM; matrixM = NULL; assert(matrixM == NULL); delete[] sum_rowsM; sum_rowsM = NULL; assert(sum_rowsM == NULL); delete[] sum_colsM; sum_colsM = NULL; assert(sum_colsM == NULL); }
不过要提醒你:手动置空指针只有在之后还要用到这些指针(比如判断是否已经释放)的时候才有意义,像destroy这种清理函数,执行完之后对象大概率不会再被使用,所以手动置空其实不是必须的,去掉那些多余的断言反而更简洁。
另外补充个小知识点:C++标准里从来没有规定delete/delete[]要修改指针的值,不同编译器可能有不同实现,但几乎所有主流编译器都不会自动把指针置为NULL,所以以后别再做这种断言啦!
备注:内容来源于stack exchange,提问作者Arol Nokam
相关产品推荐
相关产品推荐

