Asked at Squarepoint Capital, Jump Trading
Theory: C++ InternalsRead the problem, hints and solution here. The editor needs a bigger screen: open this page on a laptop to write and run your code.
Half of C++ interviewing at systems-minded funds is one question asked many ways: do you actually understand object lifetime? The cleanest probe is wrapping a C-style resource API in an owning handle, because every mistake (leak, double release, broken move) is observable and every fix is a rule-of-five decision.
The scaffold provides a fake C API, fake_api, which you must not modify:
acquire_resource() returns a fresh positive id and release_resource(id)
returns it. The API is instrumented: acquired_count(),
released_count(), live_count() and double_release_count() (releases
of an id that was not live) let the tests watch your handle's behaviour
from outside. That instrumentation stands in for the malloc/free, fd
open/close or exchange-session handles a real wrapper would manage.
Implement ResourceHandle, a move-only owning wrapper:
ResourceHandle(): acquires a resource from fake_api and owns it
(resource acquisition is initialization).valid() == false, id() == 0).long long id() const (0 when empty) and bool valid() const are
provided in the scaffold.Mark the move operations noexcept: one hidden test stores handles in a
std::vector and pushes through several reallocations, which is exactly
where a missing or throwing move turns into copies or double releases.
[]{ fake_api::reset_instrumentation(); { ResourceHandle a; ResourceHandle b; } return std::tuple<long long, long long, long long, long long>{fake_api::acquired_count(), fake_api::released_count(), fake_api::double_release_count(), fake_api::live_count()}; }()
// (2, 2, 0, 0) (two acquired, two released, no double release, nothing live)
[]{ fake_api::reset_instrumentation(); std::vector<long long> out; { ResourceHandle a; long long ida = a.id(); ResourceHandle b(std::move(a)); out.push_back(a.valid() ? 1 : 0); out.push_back(b.id() == ida ? 1 : 0); out.push_back(fake_api::acquired_count()); out.push_back(fake_api::live_count()); } out.push_back(fake_api::released_count()); out.push_back(fake_api::double_release_count()); return out; }()
// [0, 1, 1, 1, 1, 0] (move transfers the id; only one acquire, one release)
fake_api namespace; the tests call
reset_instrumentation() themselves.long long plus
discipline.Run your code to check it against the sample tests. Results appear here.