Say I have something like this
extern "C" void make_foo (char** tgt) {
*tgt = (char*) malloc(4*sizeof(char));
strncpy(*tgt, "foo", 4);
}
int main() {
char* foo;
make_foo(&foo);
std::string foos{{foo}};
free(foo);
...
return 0;
}
Now, I would like to avoid using and then deleting the foo
buffer. I.e., I'd like to change the initialisation of foos
to something like
std::string foos{{std::move(foo)}};
and use no explicit free
.
Turns out this actually compiles and seems to work, but I have a rather suspicious feel about it: does it actually move the C-defined string and properly free the storage? Or does it just ignore the std::move
and leak the storage once the foo
pointer goes out of scope?
It's not that I worry too much about the extra copy, but I do wonder if it's possible to write this in modern move-semantics style.
std::move
(it moves theconst char *
, not the actual data) and leak. You cannot use a predefined buffer withstd::string
– Retroversion#include <cstdlib>
and thenstd::free
? I certainly can't do anything about themalloc
in the C code, and why would this be a problem anyway? – Vacuvastd::string
did take ownership it would call thedestroy
for the default allocator which callsdelete
and notfree
. Mixingdelete
withmalloc
is a no-no. – Miraculousstd::string_view
(c++17) – Jaleesastd::move
doesn't actually move anything, it just performs a cast. – Dirigiblestrncpy
here is belt-and-suspenders programming, with broken suspenders. The code allocates an array of 4char
, and copies 4 characters into it. Fine, no problem. But if it was modified to copy 5 characters instead,strncpy
would happily stop copying after the first 4 characters then return, producing an unterminated char array. That will almost certainly result in a memory access out of bounds later in the program.strncpy
is not a "safe" replacement forstrcpy
for any reasonable definition of "safe". – Clayborne