char* operator-(){ char *new_str = new char[strlen(str_)+1]; for (int i = 0; i < strlen(str_); i++) { if (str_[i] != ' ')new_str[i] = (char) ((int) str_[i] - 32); else new_str[i] = str_[i]; } new_str[strlen(str_)] = '\0'; return new_str; } 

How to prevent memory leak in this piece of code? Or is it not?

Closed due to the fact that the question is too common for participants Vlad from Moscow , HamSter , fori1ton , αλεχολυτ , iluxa1810 13 Nov '16 at 11:39 .

Please correct the question so that it describes the specific problem with sufficient detail to determine the appropriate answer. Do not ask a few questions at once. See “How to ask a good question?” For clarification. If the question can be reformulated according to the rules set out in the certificate , edit it .

  • First tell us exactly where you see the leak. - PinkTux
  • @PinkTux If he knew, he would say. And so he asked just in case. :) - Vlad from Moscow
  • @PinkTux, my logic is simple and linear. If you see new, be sure to delete. Or not? - Chad
  • delete is not needed here, since you are returning new_str . Is there anywhere else - you know better, the local telepaths went on vacation yesterday :) - PinkTux

3 answers 3

As such, there is no leakage. But - your operator returns a pointer to dynamically allocated memory, and if you lose it (just by not using this value) or forget to free it, then you will get it.

Therefore, it is always better not to simply return a pointer. It would be better to return a string of type string - whose destructor will take care of freeing memory for you.

Here are some examples for better understanding:

 char * f() { char * q = new char[10]; return q; }; int main() { f(); // Утечка char * c = f(); // Утечки нет, но нужно помнить delete[] c; // о необходимости удаления и делать это самому unique_ptr<char> s(f()); // Утечки нет - об освобождении // памяти позаботится unique_ptr } 

    The interface of your function assumes that the function dynamically creates a string and returns it to the user of the function. The owner of the pointer is the code that called the function. This calling code is responsible for destroying the string it received from the function if it is useless.

    Another thing is that the function is written, let's say, not in the best style.

    First, since this function appears to be a member function of the class, and it does not change the class object itself, it is better to declare it with the const qualifier.

    It is also not clear what the magic number 32 means. If this is a space code in the ASCII character table, then it is better to write a space character instead of the given magic number. If this is not the case, then it is better to enter the mnemonic name for this literal so that it has some meaning for the reader of your code.

    In your function, the function std::strlen is called three times.

    The function might look like this.

     char * operator-() const { size_t n = std::strlen( str ); char *new_str = new char[ n + 1 ]; for ( size_t i = 0; i < n; i++ ) { if ( str_[i] != ' ' ) new_str[i] = str_[i] - ' '; else new_str[i] = str_[i]; } new_str[n] = '\0'; return new_str; } 

    Please note that it would be a mistake to use this function as follows.

     std::cout << -obj; 

    Where obj is an object of the class where this operator is defined. In this case, the pointer returned from the function will be lost. You should first assign it to some variable. for example

     const char *s = -pbj; std::cout << -obj; delete [] s; 

    To avoid problems of this kind, it is better to use the standard class std::string instead of pointers to character arrays.

    In this case, the function definition might look like this.

     #include <string> //... std::string operator-() const { size_t n = std::strlen( str ); std::string new_str( n, ' ' ); for ( size_t i = 0; i < n; i++ ) { if ( str_[i] != ' ' ) new_str[i] = str_[i] - ' '; else new_str[i] = str_[i]; } return new_str; } 

    And then you can, without fear of memory leaks, write

     std::cout << -obj; 

    Also consider the option when the operator returns not just a string, but an object of your own class. For example,

     String operator-() const; 

    Then, since, as I suppose, the class has an appropriate destructor, you can also feel free to write

     std::cout << -obj; 

    provided that you have defined the operator << output statement for your class.

    • Thanks for the detailed answer! The only thing that remains unclear is: - I call the function itself to output to the stream (via cout), what happens with the allocated memory? // this operator is a method of my class String; below is the function call String str; cout << "operator-: " << -str << endl; - Chad
    • I understand that she magically freed herself? - Chad
    • @Chad If you do not delete it, then a memory leak occurs. Therefore, before outputting to the stream, you need to save the returned value of the pointer in the variable and then delete the string using this variable. - Vlad from Moscow

    A memory leak is a situation when a dynamic memory block is allocated in your program, but subsequently all information is lost, allowing you to get a pointer to the beginning of this block (including with the aim of releasing it).

    The piece of code given to you is taken out of context so much that it is impossible to judge whether there is a memory leak in it or not. In particular, if the calling code ignores the return value of the operator-() function, then a memory leak definitely occurs. If the calling code retains this value, then memory leaks do not formally arise.