Hi, ruSO!

I got acquainted with C ++ relatively recently, but I am far from knowing Zen. From November to the "pluses" did not touch at all. The other day I decided to return to the abandoned pet-project, which began to write while studying a language, at the same time to recall the "pluses" and continue my study. In the project there was a problem with the allocation of memory for data and its subsequent cleaning. At the time of writing the project, I could not deal with this problem, but due to lack of time I abandoned it altogether.

Yesterday I spent a couple of hours in the debugger, rewrote 80% of the code of the class where the error occurred (the class architecture was completely curved) and got rid of the errors of memory allocation and cleaning.
The application finally runs without any errors. Finally decided to check the correctness of memory cleanup. I run the debug again and watch carefully for the data I am deleting. Strangely, delete myData happens, but the data remains. I thought that in half a year I had time to forget the basics of C ++ and how pointers work. To check, I wrote a quick simple example:

 uint* a = new uint; *a = 5; cout<<"Before delete:\t\t"<<*a<<" on address: "<<a<<endl; delete a; cout<<"After delete:\t\t"<<*a<<" on address: "<<a<<endl; *a = 7; cout<<"After delete & set:\t"<<*a<<" on address: "<<a<<endl; 

Looking at the results of the code, I fell into the sediment:

 Before delete: 5 on address: 0x7fe994c02700 After delete: 5 on address: 0x7fe994c02700 After delete & set: 7 on address: 0x7fe994c02700 Process finished with exit code 0 

Apparently, I am not a fool, I remember the basics, and this is a problem even in simple examples, and not just in my code. But that's not all! Now we add two lines after the third cout :

 delete a; cout<<"After second delete: "<<*a<<" on address: "<<a<<endl; 

Run the debugger, see the result and quietly crawl under the table:

 Before delete: 5 on address: 0x7f8193500000 After delete: 5 on address: 0x7f8193500000 After delete & set: 7 on address: 0x7f8193500000 my_test_prog(1774,0x7fffafdc8340) malloc: *** error for object 0x7f8193500000: pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug Signal: SIGABRT (signal SIGABRT) Terminated due to signal 6 Process finished with exit code 0 

No, I certainly understand that it is impossible to delete something that has already been deleted. But folks, you can safely access the pointer after the first memory is cleared (on the second attempt, the application crashes, which is not surprising), get the address of the memory cell, extract the value from it, write a new one, etc. Of course, in my code there is no such nonsense as double deletion of the allocated memory, I added this line only for checking that if the memory cell remains selected, then it can be deleted. But no. The pointer is saved, the value is saved, and you can not delete!

I set the breakpoints on each line and followed the pointer a . After the first call to delete its address did not change, the value did not disappear and, as can be seen above, it was easy to work with it. Well, the second delete simply did not work. At the time of program completion, the a pointer was still pointing to the memory cell with the address 0x7f8193500000 , even after trying a second delete .

I still attend the idea that I am a noob and do not understand something, but according to the logic of things, when clearing the memory, the cell should be completely erased. How is that? If I remember correctly, when accessing a memory cell that was cleared, either an error at the execution stage should crash (with the program terminating abnormally, and in my case only when calling the second delete ), or “abracadabra” instead of the value that was written to this memory location. And nothing happens for me, so I ask you for help and advice.

Thank you in advance for your help.
Regards, Yuri.

Work Environment:

 IDE: CLion, C++17 OS: macOS High Sierra (v10.13.3) 

PS: if there is a lot of "water" in the question, I sincerely apologize. It was always difficult for me to briefly express my thoughts "essentially", and besides, I did not go to ruSO for a very long time, and I lost a bit of a grip. :)

    1 answer 1

    The delete operator does not change the value of the passed pointer, but makes the pointer invalid. But the programmer is responsible for the fact that the program will not dereference of invalid pointers. Any attempt to do so leads to indefinite behavior.

    • Thanks for the information. But what happens to the memory itself? Is it cleaned at all or not? In the examples given, the memory still contains the value written to it. If it is not cleared (released), with large amounts of information, will there not be an overflow of RAM? I am not even worried about the fact that through an invalid pointer one can still access memory, but the fact that memory is not cleared! - intro94
    • @ intro94 From the point of view of the built-in allocator, memory is freed. But its contents may not change, or change randomly (if the same block is allocated in another stream). The virtual memory of the process can remain in it and be reused (which usually happens) or given back to the system. What was printed After delete: 5 on address: 0x7fe994c02700 says nothing about whether the memory is freed or not. - VTT
    • If I understand your explanations correctly, then when allocating memory (for example, through new ), the allocated memory is blocked by this process, and when using the delete operator, the pointer becomes invalid, and the allocated memory is freed by the process, although its contents may not be cleared immediately, and is available for allocation other processes? And because of this, there will be no RAM overflow? - intro94
    • @ intro94 Memory is actually allocated by the operating system. But in c ++, the memory allocator is used on top of the system one, which tries to minimize the number of system calls and usually re-uses memory. "The pointer becomes invalid" implies that its dereference is an indefinite behavior, nothing more. And the memory, which he previously pointed out, could be reused, or could not be, could remain in the process, but could not remain, the meaning of which could change there, and could not change. - VTT
    • Hmm ... I understand a little. Thanks for the clarification, now I am calm. So you can with a clear conscience assume that there are no memory leaks and errors in the code are corrected. :) I hope in the future I will have a little less leg shots than I did yesterday. xD - intro94