-1

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 allocatederror. 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?

bobinthebox
  • 101
  • 4
  • 1
    `delete[] s;` what? why? did Stroustrup ask you to copy a string and then delete the original? what's the point of such copying? and of course you don't know whether the original is allocated on the free store, so you cannot even *think* about deleting it. – n. 1.8e9-where's-my-share m. Sep 22 '21 at 09:38

1 Answers1

1

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.

463035818_is_not_a_number
  • 88,680
  • 9
  • 76
  • 150