Do I need to reset the pointer after using the operator delete ? Or does it, unlike the malloc function, reset the pointer itself?

 int *v = new int(5); delete v; v = nullptr; 

And what about deleting the pointer in the following code:

 (1) int *a = new int[10]; (2) delete [] a; (3) delete a; (4) a = nullptr; 

Do I need to delete the pointer, as in the third line? If not, then I understand that it is necessary to reset it, as in the fourth?

  • 3
    delete frees the area of ​​memory that you allocated earlier with new, and the pointer itself, after releasing the memory, will point to some random cell - bsuart
  • one
    @ bsuart2017, no, not random. In RAM, there is a very specific (in the context of a specific OS) range, which is reserved by the OS and is not available to the user - this is the range that is used to detect null pointers. - isnullxbh
  • one
    @isnullxbh, yes there is a certain range, but in this context the question did not make sense to explain which specific cell the pointer would point to, this is a completely separate question and topic - bsuart
  • one
    @ bsuart2017, so if it wasn’t in the question, why did you add this: "..and the pointer itself, after freeing the memory, will point to some random cell." ? After all, you did not ask about it. Now I will explain why I made a remark to you: You would not deny that after the pointer began to point to a “random” cell, there could be something in this cell that would not have caused UB, SF, etc. d. when pointer dereferencing? And this is somehow not good, do not you think? - isnullxbh
  • one
    @isnullxbh, I do not understand what the actual problem is. I did not give an answer to the current question, but simply made a comment, because I knew that someone would give a detailed answer with all the explanations. I agree that my comment is not entirely correct, because it is really not a random cell, I agree with your remark. - bsuart

4 answers 4

This code has an undefined behavior, as there is an attempt to double-delete the memory addressed by the pointer a , and the wrong delete statement is used a second time.

 int *a = new int[10]; delete [] a; delete a; a = nullptr; 

It is usually advised to reset the pointer after releasing the memory indicated by it, so that when you try to delete the memory again, you will not get a program execution error. For example, this code is correct.

 int *a = new int[10]; //... delete [] a; a = nullptr; //... delete [] a; 

since you can call the operators delete and delete[] for null pointers.

However, by doing so you mask a potential error in your program. It is possible that your program is malfunctioning and, indeed, is trying to at least twice delete the same area of ​​memory. If you assign a nullptr value to the pointer, then it will be difficult for you to detect this error.

The argument for assigning a value to nullptr is that if you have a pointer equal to nullptr , then it will be easy for you to detect an attempt to access memory using that pointer. However, in reality this is not always the case. For example, the z/OS operating system on IBM mainframe allows you to read memory using a null pointer. It only does not allow to write data on such a pointer. Therefore, again, by assigning a nullptr value nullptr pointer, you can disguise the error when you access the readable memory at the zero address. In my experience, such a mistake is often made by C programmers working on the IBM mainfarme when using standard string functions from the <string.h> library, calling, for example, the string comparison function strcmp , when one of the pointers is NULL . As a result, the program has an undefined behavior. But to detect such an error is very difficult.

On the other hand, explicitly assigning a nullptr value to the nullptr facilitates self-documenting of the source code. The reader is given to know that, starting with this assignment, the pointer is invalid.

So there is no universal rule. It is advisable to make it so that the lifetime of the variable designating the pointer matches the lifetime of the memory it points to. In this case, there is no point in assigning a nullptr value to the nullptr , since the pointer ceases to exist at the same time as the memory addressed by it is deleted.

Most often, you can come across a code where either initialization of the pointer by zero is used, or assignment to it null values ​​in old C programs, since previously, before adopting the C99 standard, variables could be declared only at the beginning of the code blocks. Therefore, between the declaration of the pointer and its use or between the removal of the memory addressed by the pointer and the termination of the pointer itself, there are often many lines of code that are difficult to cover with one look at the source text. Therefore, assigning null values ​​to pointers allowed the code reader to more easily understand the logic of this or that cumbersome function.

Currently, both in C and in C ++, you can declare variables anywhere in a code block, and therefore you can narrow the lifetime of variables to the part of the code where they are directly used. Therefore, there is no longer any need to assign a null value to the "spent" pointer.

Try to declare variables in the smallest declaration area where they are directly used. so that there are no "pending" variables that cannot be said about whether they are used elsewhere in the code, or whether they are no longer used.

In addition, in C ++ there are so-called smart pointers, as well as corresponding containers that themselves take care of deleting the memory that is no longer in use. The allocation and deletion of memory "manually" is fraught with errors in the program.

    Let's distinguish between a pointer and the data it points to.

    The delete operator works with the memory pointed to by the pointer. Moreover, if you allocated memory with new , then you need to free with delete . And if with the help of new[...] , then you need to free with the help of delete[] . (The responsibility for this lies with you.)

    The delete operator does not change the pointer, but after delete points to invalid memory (most likely, this memory will be allocated to someone else for its purpose). It makes sense to independently assign the value of nullptr pointer after delete , so as not to accidentally use invalid memory. But this is not necessarily and rather a precaution for you, rather than a language requirement.

    There is only one requirement for the language: after delete you should not access the allocated memory system by pointer. How you ensure this is all your concern.

    Yes, and the second time you can not delete the object by the pointer! Because it is generally impossible to access the remote memory (an attempt to delete is also an appeal). Therefore, line (3) incorrect on both sides: this is the repeated deletion of memory, which is prohibited, and deletion without [] , although the memory was allocated with [] .

      With the pointer, you can do whatever you want :) delete doing nothing on the variable itself. You can reset it, you can - no, but then just remember that it now indicates where it is not clear, and this value can no longer be used.

      In your example, delete correctly as in line 2.

      (In a whisper: for int , though, due to the lack of destructors, the third method will come down ... but in general, this is a mistake! In a whisper, so that no one takes it as permission to do this :) I just mentioned it, but I insist on not to do so in any way! )

      Line 4 is up to you ...

      • one
        Pro int can be more? - yrHeTaTeJlb
      • 2
        @yrHeTaTeJlb, simple types have no destructors. - ixSci
      • one
        @yrHeTaTeJlb Well, everything has already been told to you :) Exactly - when there is nothing to call, delete simply frees the memory. Theoretically, new[] and new are different operations, so delete , where you need delete[] , can lead to problems ... but so far I have not heard of a compiler that would really lead to them for fundamental types. However, in any case, personally, I categorically do not recommend doing so ... Now I will strengthen this moment in the answer :) - Harry
      • four
        @yrHeTaTeJlb, all known implementations to me use the banal malloc / free , which are not able to distinguish one element from the set, therefore, in practice, the memory should be freed correctly. This does not negate the fact that such application itself is UB. - ixSci
      • 2
        @yrHeTaTeJlb Well, that's right, you can't. But in wartime, as they say, the right angle reaches 100 degrees :) Ie there is perfect C ++, and there is - imperfect C ++, as one very interesting book was called, which talked about how this or that compilers actually work (unfortunately, it’s too old). Now I looked at the sources of Open Watcom - there clearly delete[] simply causes delete . There are no other sources, but I showed the test drive on VC ++ ... - Harry

      This is what is written in the smart book .. When the delete operator is applied to a pointer, the area of ​​dynamic memory that it points to is released. Re-applying the delete operator to the same pointer will cause the program to hang. When releasing the dynamic memory area, it is recommended that the pointer associated with it be set to zero (0). Calling the delete operator for the null pointer will be completely painless for the program. Example:

       Animal *pDog = new Animal; delete pDog; // освобождение динамической памяти pDog = 0; // присвоение указателю нулевого значения delete pDog; // вполне безопасно 

      ps book on the standard 98 years.

      • 2
        It is to hang up - hardly. To UB - yes. And this UB can even be used for hacking. - Harry
      • one
        @Harry ub leads, with a very large percentage, to the hang of the program. - perfect
      • four
        In my opinion, where more likely to crash, and not to hang. - Harry
      • one
        @Harry to be exact depends on the program itself. if there are many cycles there (and this is the majority of programs) then the probability of creating an infinite loop is very high. in general, du can manifest itself in general in another program or even in the OS itself (including hanging them). - perfect
      • one
        @Harry, but if the program crashes with a message, then with a great degree of confidence I can say that it isn’t du system interception. - perfect