I am learning c++ and i stumbled once again on a new issue.
I do need to allocate a C array for a library to use, but in a safe way, ofcourse. I already found that delete[]; at the end of method fails miserably.
OLD, not that good:
float *buf;
try {
buf = new float[daswidth*chans_info.chans*sizeof(float)];
}
catch (std::bad_alloc& ba) // sometimes it throws ! so i do need to stop my execution.
{
if (DEBUG) tekstasFormat(L"WARNING: bad alloc caught: %s", ba.what());
return; // skip this iteration then.
}
//... OUR CODE
delete[] buf;
So what i tryed to use which works perfectly instead of my old allocation and deletion:
float *buf;
std::shared_ptr<float> safe_buf(new float[daswidth*chans_info.chans*sizeof(float)], [](float *p) { delete[] p; });
// OR BOOST EQUIVALENT
boost::shared_array<float> safe_buf(new float[daswidth*chans_info.chans*sizeof(float)]);
buf = safe_buf.get();
And we do never leak, everyone is happy. But how to catch new_alloc throws now ?!
if i will allocate shared_ptr in a new{} scope after new it gets destroyed... Explain me and noobs like me for the future a bit more. How to handle exceptions in this case ?
Prefer std::unique_ptr
to shared_ptr
. It's far faster.
std::unique_ptr<float[]> buf; //construct
try {
buf.reset(new float[daswidth*chans_info.chans*sizeof(float)]); //give memory
}
catch (std::bad_alloc& ba) // sometimes it throws ! so i do need to stop my execution.
{
if (DEBUG) tekstasFormat(L"WARNING: bad alloc caught: %s", ba.what());
return; // skip this iteration then.
}
However, as Ben
said, there's pretty much no reason to use a float[]
like this. Instead, use std::vector
. Yes, even for most* C interop.
std::vector<float> buf;
try {
buf.resize(daswidth*chans_info.chans*sizeof(float)); //give memory
}
catch (std::bad_alloc& ba) // sometimes it throws ! so i do need to stop my execution.
{
if (DEBUG) tekstasFormat(L"WARNING: bad alloc caught: %s", ba.what());
return; // skip this iteration then.
}
function_expecting_float_pointer(buf.data()); //use .data() to get the `float*`
*don't use std::vector
if the C code will ever "reallocate" the pointer for you. Instead, use std::unique_ptr
, and (1) release the memory, (2) pass to C, (3) reset with pointer returned from C.