C++类成员函数调用printf/cout时触发段错误的原因是什么?
问题根本原因
你遇到的堆破坏错误和混用printf/cout没有任何关系,是堆内存越界写导致的,问题出在内存分配的语法写错了:
- C++中,
new double(n)的含义是分配1个double类型的内存空间,并将其初始化为值n,而非分配长度为n的double数组。分配数组的正确语法是new double[n](方括号而非圆括号)。 - 你的带参构造函数中,传入的degree是7,随后你执行了
n++得到8,然后用new double(n)仅分配了1个double的空间,后续循环往这个地址写入8个double值,直接越界改写了堆上的元数据,当后续putchar/cout需要调用malloc分配stdout缓冲区时,就会检测到堆结构损坏,触发崩溃。 - 取消
printf("\n")的注释后崩溃消失属于未定义行为的随机表现:这行printf会提前触发stdout缓冲区的分配,你越界写的堆空间刚好踩在了已经分配的缓冲区上,没有破坏malloc的核心元数据,因此暂时隐藏了问题,但内存越界的bug依然存在。
另外你代码里还有两个关联错误:
- 你在
Print方法中调用了this->cf(0),但类定义中只声明了cfp方法,没有声明cf,属于粘贴遗漏或者定义缺失。 - 如果你分配的是数组,释放内存必须用
delete[],而非delete,你当前的析构函数用delete释放数组也会导致未定义行为。
修复方案
快速修复写法
修改构造函数和析构函数的内存操作:
// 默认构造函数 Poly::Poly() { this->degree = 0; // 分配长度为1的数组,用方括号 this->coefficients = new double[1]; this->coefficients[0] = 1.; } // 带参构造函数 Poly::Poly(size_t n, ...) { va_list coefs; va_start(coefs, n); this->degree = n; size_t count = n + 1; // 分配数组用方括号 double *cfs = new double[count]; this->coefficients = cfs; for (size_t i = 0; i < count; i++) { cfs[i] = va_arg(coefs, double); } va_end(coefs); } // 析构函数 Poly::~Poly() { // 释放数组用delete[] delete[] this->coefficients; }
更安全的推荐写法
抛弃裸指针和可变参数,用C++标准容器管理内存:
#include <vector> #include <initializer_list> class Poly { private: std::vector<double> coefficients; size_t degree; public: Poly() : degree(0), coefficients{1.} {} // 用initializer_list传系数,无需处理可变参数 Poly(size_t n, std::initializer_list<double> coefs) : degree(n), coefficients(coefs) {} void Print() const { // 直接用coefficients[i]访问即可,不需要自己实现内存管理 } // 不需要手动写析构函数,vector自动释放内存 };
内容的提问来源于stack exchange,提问作者Sayan
相关产品推荐
相关产品推荐

