I'm solving the following exercise (17.4) from Stroustrup's PPP book:
Write a function
char* strdup(const char* )
that copies a C-style string into memory it allocates on the free store. Don't use any standard library function.
Here's my implementation, which compiles just fine. I have a question about an error message that I found when I run the function.
#include <iostream>
#include <string>
char* strdup(const char* s) {
if (s==0) return 0;
// get number of char in s
int n = 0;
while (s[n] != 0)
n;
// allocate memory with room for terminating 0
char* pc = new char[n 1];
// copy string
for (int i = 0; s[i]; i)
pc[i] = s[i];
pc[n] = 0; // zero at the end: it's a C-style string
delete[] s;
return pc;
}
int main()
try {
std::string str;
char* cstr;
while (std::cin>>str && str!="quit") {
cstr = strdup(&str[0]);
std::cout << cstr << "\n";
delete[] cstr;
}
}
catch (std::exception& e) {
std::cerr << "exception: " << e.what() << std::endl;
}
catch (...) {
std::cerr << "exception\n";
}
It compiles, but when I run it and I write the first character, I have a pointer being freed was not allocated
error. If I remove delete[] s
, then I have no memory leak and it runs just fine. But why is (apparently) correct to do not delete[]
the s
? Is it because it has not been allocated with new
?
CodePudding user response:
A std::string
does manage the memory it uses to store the string. In main
you do
std::string str;
and
cstr = strdup(&str[0]);
but your strdup
calls delete[] s;
on the parameter.
This is what you already know. Now consider that the destructor of std::string
does already clean up the memory when it goes out of scope. The buffer used by the std::string
cannot be deleted twice. You shall not call delete
on &str[0]
. You only need to delete
objects that you created via new
.
Also there is small string optimization. In this case &str[0]
does not point to a heap allocated buffer which you could delete.
PS: You are using 0
when you should rather use nullptr
for pointers and '\0'
for the null terminator.