在下面的代码中,我遇到了一个问题。它表现为bad_alloc异常,这是因为传递给reader
的参数CompressedBufferReader
是一个错误的字符串。
class FileReader {
FILE *file;
protected:
unsigned char *data; // local copy
long size;
public:
FileReader(const char *filename);
~FileReader();
unsigned long getSize();
unsigned char *getFileData();
};
class CompressedBufferReader {
unsigned char *buffer;
unsigned long len;
public:
CompressedBufferReader(unsigned char *);
~CompressedBufferReader();
unsigned char *getBuffer();
unsigned long getLength();
};
CompressedBufferReader::CompressedBufferReader(unsigned char *srcCompressed) {
len = 0; buffer = 0;
len = GetDecompressedBufferSize(srcCompressed);
buffer = new unsigned char[len]; if (!buffer) throw std::runtime_error("Cannot allocate!");
WriteDecompressedBuffer(buffer, len, srcCompressed);
}
CompressedBufferReader::~CompressedBufferReader() {
delete[] buffer;
}
unsigned char *CompressedBufferReader::getBuffer() {return buffer;}
unsigned long CompressedBufferReader::getLength() {return len;}
// similar interface to FileReader. Does not inherit because it does not benefit from doing so.
class CompressedFileReader {
CompressedBufferReader reader;
public:
CompressedFileReader(const char *filename);
unsigned char *getFileData();
unsigned long getSize();
};
CompressedFileReader::CompressedFileReader(const char *filename) : reader(FileReader(filename).getFileData()){} // this line is causing the problem
unsigned char *CompressedFileReader::getFileData() { return reader.getBuffer(); }
unsigned long CompressedFileReader::getSize() { return reader.getLength(); }
更具体地说,似乎我匿名创建的FileReader在其数据内容可以传递给reader
的构造函数CompressedBufferReader
之前被取消分配。
问题是我不能以允许我正确实例化CompressedFileReader
的方式编写FileReader
的构造函数,因为我打算使用CompressedBufferReader
的构造函数,这意味着我必须在构造函数的主体之前调用它。有点抓 - 22。这个问题是如何解决的?
答案 0 :(得分:3)
您的代码违反了一条非常重要的规则,即“三巨头”
如果您的班级有任何的析构函数,赋值运算符或副本 构造函数然后它应该所有三个。
原因是如果存在自定义析构函数,那么很可能自动合成的赋值运算符和复制构造函数(只是逐个成员的复制结构或赋值)是不正确的。< / p>
这个规则非常重要,如果您碰巧找到一个案例,其中有一个例子是析构函数但是默认的复制构造函数,那么至少在注释中写一下你没有忘记复制构造函数和/或任务,但自动提供的将是正确的。
如果您的类不能被复制或复制构造,那么通过声明它是私有的并且不写入实现来禁止该操作。
在特定情况下,当复制或分配两个类中的任何一个的实例时,将复制指针,但数据将被销毁两次。
答案 1 :(得分:2)
我没有看到使用构造函数的方式存在问题,这会导致bad_alloc(尽管代码看起来很笨拙)。让我们看看导致问题的行的执行 -
CompressedFileReader::CompressedFileReader(const char *filename) :
reader(FileReader(filename).getFileData()){}
执行以下步骤:
FileReader
。它的构造函数使用filename
调用,它是const char*
。data
的{{1}}成员中。FileReader
上调用getFileData()
,返回FileReader
的值,我认为这是data
。unsigned char *
是一个reader
,是使用CompressedBufferReader
构建的。unsigned char *
被破坏。因此,问题不在于构造的顺序,也不在于临时FileReader
的生命周期。你应该研究一些未知的事情:
FileReader
的构造函数是否创建了有效的缓冲区,并将其存储在FileReader
?data
是否返回创建的缓冲区?getFileData()
是否为有效缓冲区返回正确的值?GetDecompressedBufferSize()
抛出,我们的代码没有?{/ li>
醇>
最后,您可能希望简化代码。像这样的结构不是很易读。当然,使用像矢量这样的标准容器会使它更安全。