Reputation: 8572
In order not to have to remember to delete, we are using unique_ptr to manage the memory. We were under the impression that we can write and read in the memory, just that deletion is up to the smart pointer. However, the following code crashes on i=7220 with a segfault.
What is wrong?
#include <memory>
using namespace std;
int main() {
const uint32_t n = 40000000;
uint64_t*p = new uint64_t[n]; // this works, but we have to delete the memory or leak
for (int i = 0; i < n; i++)
p[i] = i;
unique_ptr<uint64_t> mem = make_unique<uint64_t>(n);
uint64_t* p1 = mem.get();
for (int i = 0; i < n; i++) // this crashes at i=7220
p1[i] = i;
return 0;
}
Upvotes: 2
Views: 185
Reputation: 29985
Aside from the fix other answers mentioned, you likely don't want to use make_unique
here. make_unique
will zero-out every single element (40 million ints!) and you immediately overwrite them. Your options are to use make_unique_for_overwrite
which requires C++20, or to use new
:
#include <cstdint> // for uint64_t
#include <memory> // for unique_ptr, unique_ptr<>::pointer
#include <numeric> // for iota
int main() {
auto const n = 40'000'000;
auto const p = std::unique_ptr<std::uint64_t[]>{new std::uint64_t[n]};
std::iota(p.get(), p.get() + n, 0);
}
Upvotes: 2
Reputation: 117658
unique_ptr<uint64_t> mem = make_unique<uint64_t>(n);
This allocates one uint64_t
dynamically with the value n
.
You want:
unique_ptr<uint64_t[]> mem = make_unique<uint64_t[]>(n);
This specialization allocates an array of uint64_t
with n
elements, and has an operator[]
overload which makes the below possible:
for (int i = 0; i < n; i++)
mem[i] = i;
So, there's no need to do uint64_t* p1 = mem.get();
Upvotes: 10
Reputation: 37578
unique_ptr<uint64_t>
is a pointer to a single uint64_t
value. In order to make it store an array you need to use array of unknown bound syntax:
unique_ptr<uint64_t[]> mem = make_unique<uint64_t[]>(n);
or just
auto mem{make_unique<uint64_t[]>(n)};
Note that this variant overloads operator [] so there is no need to create an intermediate raw pointer uint64_t* p1 = mem.get();
Upvotes: 5