I've come across a weird segfault while trying to push a class containing a pointer of an ofstream to a vector. I have narrowed the problem down to the simplest test case possible:
Test.h
#ifndef __TEST_
#define __TEST_
#include <fstream>
#include <string>
class Test {
public:
Test(std::string path);
~Test();
private:
ofstream* ofstr;
}
#endif
Test.cpp
#include "Test.h"
Test::Test(std::string path) {
ofstr = new ofstream(path, std::ios::app);
}
Test::~Test() {
delete ofstr;
}
main.cpp
#include <vector>
#include "Test.h"
int main() {
Test test("hello.txt");
std::vector<Test> vec;
vec.push_back(test); // segfaults
}
I think that the segfault has to do with the destructor for Test, but I'm not sure why. The segfault occurs when I use emplace_back as well.
The first problem that your code suffers from is that you are not following The Rule of Three.
However, your problem is deeper than what is suggested to follow The Rule of Three.
Say your class had a different member variable than std::ofstream*
.
class Test {
public:
Test(int in) : ptr(new int(in)) {}
~Test();
private:
int* ptr;
}
You can update that class to follow the rule of three by making the sure that you do the right thing in the copy constructor and the copy assignment operator. In both of those, you'll have to use something along the lines of:
ptr = new int(*copy.ptr);
That works for most types. However, that does not work for std::ofstream
since std::ofstream
does not have a copy constructor or a virtual
function that can return a pointer by cloning the object.
In your case, neither of the following is an option.
ofstr = new ofstream(*copy.ofstr);
ofstr = copy.ofstr->clone();
To get around that problem, you can use std::shared_ptr<std::ofstream>
.
class Test {
public:
Test(std::string path);
~Test();
private:
std::shared_ptr<std::ofstream> ofstr;
}
When you do that, not only do you fix your problem but also, you can let the compiler generated destructor, copy constructor, and copy assignment operator do the right thing. Your class definition can be simplified to:
class Test {
public:
Test(std::string path);
private:
std::shared_ptr<std::ofstream> ofstr;
}
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments