Commit 7dfd49f2 authored by Nick Terrell's avatar Nick Terrell Committed by Facebook Github Bot

Fix memory leak when exception is thrown

Summary: F14NodeSet::insert() leaks memory when construction throws.

Reviewed By: yfeldblum, nbronson

Differential Revision: D16399317

fbshipit-source-id: 4c9385288dd212469dfbd10b3e990b3533dc66d3
parent 133d8937
......@@ -849,7 +849,9 @@ class NodeContainerPolicy
auto p = std::addressof(**itemAddr);
// TODO(T31574848): clean up assume-s used to optimize placement new
assume(p != nullptr);
auto rollback = makeGuard([&] { AllocTraits::deallocate(a, p, 1); });
AllocTraits::construct(a, p, std::forward<Args>(args)...);
rollback.dismiss();
}
void moveItemDuringRehash(Item* itemAddr, Item& src) {
......
......@@ -1417,6 +1417,21 @@ TEST(F14Set, eraseIf) {
testEraseIf<F14NodeSet>();
}
template <template <class...> class TSet>
void testExceptionOnInsert() {
TSet<ThrowOnCopyTestInt> m{};
ThrowOnCopyTestInt key;
EXPECT_THROW(m.insert(key), std::exception);
EXPECT_TRUE(m.empty());
}
TEST(F14Set, ExceptionOnInsert) {
testExceptionOnInsert<F14ValueSet>();
testExceptionOnInsert<F14NodeSet>();
testExceptionOnInsert<F14VectorSet>();
testExceptionOnInsert<F14FastSet>();
}
///////////////////////////////////
#endif // FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE
///////////////////////////////////
......@@ -118,6 +118,30 @@ struct MoveOnlyTestInt {
}
};
struct ThrowOnCopyTestInt {
int x{0};
ThrowOnCopyTestInt() {}
__attribute__((__noreturn__))
ThrowOnCopyTestInt(const ThrowOnCopyTestInt& other)
: x(other.x) {
throw std::exception{};
}
ThrowOnCopyTestInt& operator=(const ThrowOnCopyTestInt&) {
throw std::exception{};
}
bool operator==(const ThrowOnCopyTestInt& other) const {
return x == other.x;
}
bool operator!=(const ThrowOnCopyTestInt& other) const {
return !(x == other.x);
}
};
// Tracked is implicitly constructible across tags
struct Counts {
uint64_t copyConstruct{0};
......@@ -593,6 +617,13 @@ struct hash<folly::f14::MoveOnlyTestInt> {
}
};
template <>
struct hash<folly::f14::ThrowOnCopyTestInt> {
std::size_t operator()(folly::f14::ThrowOnCopyTestInt const& val) const {
return val.x;
}
};
template <int Tag>
struct hash<folly::f14::Tracked<Tag>> {
size_t operator()(folly::f14::Tracked<Tag> const& tracked) const {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment