Fix memory leak for HeaderEntity instances:

the getArgumentCount() call in IfcEntityInstanceData destructor isn't virtually dispatched so it returns 0 instead of correct number of arguments => memory leak
added IfcEntityInstanceData::clearArguments() which clears all arguments and resets the attributes_ field to nullptr

Remove unnecessary copy in IfcEntityInstanceData::setArgument() when argument is created at the call site (no more leak of original argument)

Fix memory leak in IfcFile: delete entities from both byid and entity_file_map
This commit is contained in:
Adrien SCHVALBERG
2022-04-28 10:33:54 +02:00
committed by Thomas Krijnen
parent e677355438
commit e5b3455533
4 changed files with 149 additions and 125 deletions
+4 -2
View File
@@ -66,8 +66,8 @@ public:
Argument* getArgument(size_t i) const; Argument* getArgument(size_t i) const;
// NB: This makes a copy of the argument // NB: This makes a copy of the argument if make_copy is set
void setArgument(size_t i, Argument* a, IfcUtil::ArgumentType attr_type = IfcUtil::Argument_UNKNOWN); void setArgument(size_t i, Argument* a, IfcUtil::ArgumentType attr_type = IfcUtil::Argument_UNKNOWN, bool make_copy = false);
virtual size_t getArgumentCount() const { virtual size_t getArgumentCount() const {
if (type_ == 0) { if (type_ == 0) {
@@ -80,6 +80,8 @@ public:
} }
} }
void clearArguments();
const IfcParse::declaration* type() const { const IfcParse::declaration* type() const {
return type_; return type_;
} }
+26 -9
View File
@@ -1057,15 +1057,21 @@ std::string IfcEntityInstanceData::toString(bool upper) const {
return ss.str(); return ss.str();
} }
IfcEntityInstanceData::~IfcEntityInstanceData() { void IfcEntityInstanceData::clearArguments()
{
if (attributes_ != NULL) { if (attributes_ != NULL) {
for (size_t i = 0; i < getArgumentCount(); ++i) { for (size_t i = 0; i < getArgumentCount(); ++i) {
delete attributes_[i]; delete attributes_[i];
} }
delete[] attributes_; delete[] attributes_;
attributes_ = NULL;
} }
} }
IfcEntityInstanceData::~IfcEntityInstanceData() {
clearArguments();
}
unsigned IfcEntityInstanceData::set_id(boost::optional<unsigned> i) { unsigned IfcEntityInstanceData::set_id(boost::optional<unsigned> i) {
if (i) { if (i) {
return id_ = *i; return id_ = *i;
@@ -1148,7 +1154,7 @@ IfcEntityInstanceData::IfcEntityInstanceData(const IfcEntityInstanceData& e) {
for (unsigned int i = 0; i < count; ++i) { for (unsigned int i = 0; i < count; ++i) {
attributes_[i] = 0; attributes_[i] = 0;
this->setArgument(i, e.getArgument(i), get_argument_type(e.type(), i)); this->setArgument(i, e.getArgument(i), get_argument_type(e.type(), i), true);
} }
} }
@@ -1265,11 +1271,12 @@ public:
}; };
void IfcEntityInstanceData::setArgument(size_t i, Argument* a, IfcUtil::ArgumentType attr_type) { void IfcEntityInstanceData::setArgument(size_t i, Argument* a, IfcUtil::ArgumentType attr_type, bool make_copy) {
if (attributes_ == 0) { if (attributes_ == 0) {
load(); load();
} }
Argument* new_attribute = a;
if (make_copy) {
if (attr_type == IfcUtil::Argument_UNKNOWN) { if (attr_type == IfcUtil::Argument_UNKNOWN) {
attr_type = a->type(); attr_type = a->type();
} else if (a->isNull()) { } else if (a->isNull()) {
@@ -1380,7 +1387,7 @@ void IfcEntityInstanceData::setArgument(size_t i, Argument* a, IfcUtil::Argument
IfcUtil::ArgumentType t2 = IfcUtil::from_parameter_type(type()->as_entity()->attribute_by_index(i)->type_of_attribute()); IfcUtil::ArgumentType t2 = IfcUtil::from_parameter_type(type()->as_entity()->attribute_by_index(i)->type_of_attribute());
delete copy; delete copy;
copy = 0; copy = 0;
setArgument(i, a, t2); setArgument(i, a, t2, make_copy);
break; } break; }
default: default:
case IfcUtil::Argument_UNKNOWN: case IfcUtil::Argument_UNKNOWN:
@@ -1392,6 +1399,9 @@ void IfcEntityInstanceData::setArgument(size_t i, Argument* a, IfcUtil::Argument
return; return;
} }
new_attribute = copy;
}
if (attributes_[i] != 0) { if (attributes_[i] != 0) {
Argument* current_attribute = attributes_[i]; Argument* current_attribute = attributes_[i];
if (this->file) { if (this->file) {
@@ -1403,10 +1413,10 @@ void IfcEntityInstanceData::setArgument(size_t i, Argument* a, IfcUtil::Argument
if (this->file) { if (this->file) {
register_inverse_visitor visitor(*this->file, *this); register_inverse_visitor visitor(*this->file, *this);
apply_individual_instance_visitor(copy, i).apply(visitor); apply_individual_instance_visitor(new_attribute, i).apply(visitor);
} }
attributes_[i] = copy; attributes_[i] = new_attribute;
} }
// //
@@ -2260,8 +2270,15 @@ IfcUtil::IfcBaseClass* IfcFile::instance_by_guid(const std::string& guid) {
// FIXME: Test destructor to delete entity and arg allocations // FIXME: Test destructor to delete entity and arg allocations
IfcFile::~IfcFile() { IfcFile::~IfcFile() {
for( entity_by_id_t::const_iterator it = byid.begin(); it != byid.end(); ++ it ) { std::set<IfcUtil::IfcBaseClass*> entities_to_delete;
delete it->second; for (const auto& pair : byid) {
entities_to_delete.insert(pair.second);
}
for (const auto& pair : entity_file_map) {
entities_to_delete.insert(pair.second);
}
for (auto entity : entities_to_delete) {
delete entity;
} }
delete stream; delete stream;
delete tokens; delete tokens;
+4
View File
@@ -46,6 +46,10 @@ HeaderEntity::HeaderEntity(const char * const datatype, size_t size, IfcFile* fi
} }
} }
HeaderEntity::~HeaderEntity()
{
clearArguments();
}
void IfcSpfHeader::readSemicolon() { void IfcSpfHeader::readSemicolon() {
if (!TokenFunc::isOperator(file_->tokens->Next(), ';')) { if (!TokenFunc::isOperator(file_->tokens->Next(), ';')) {
+1
View File
@@ -36,6 +36,7 @@ private:
HeaderEntity& operator =(const HeaderEntity&); //N/A HeaderEntity& operator =(const HeaderEntity&); //N/A
protected: protected:
HeaderEntity(const char * const datatype, size_t size, IfcParse::IfcFile* file); HeaderEntity(const char * const datatype, size_t size, IfcParse::IfcFile* file);
virtual ~HeaderEntity();
void setValue(unsigned int i, const std::string& s) { void setValue(unsigned int i, const std::string& s) {
IfcWrite::IfcWriteArgument* argument = new IfcWrite::IfcWriteArgument; IfcWrite::IfcWriteArgument* argument = new IfcWrite::IfcWriteArgument;