Is delete allowed to modify its parameter?
Asked Answered
G

4

37

In an answer, https://mcmap.net/q/23077/-why-doesn-39-t-delete-set-the-pointer-to-null, there is a quote from Stroustrup:

C++ explicitly allows an implementation of delete to zero out an lvalue operand, and I had hoped that implementations would do that, but that idea doesn't seem to have become popular with implementers.

However, I failed to find this explicit statement in the standard. There is a part of the current draft standard (N4659), that one may interpret this way:

6.7:

When the end of the duration of a region of storage is reached, the values of all pointers representing the address of any part of that region of storage become invalid pointer values (6.9.2). Indirection through an invalid pointer value and passing an invalid pointer value to a deallocation function have undefined behavior. Any other use of an invalid pointer value has implementation-defined behavior.

Footnote: Some implementations might define that copying an invalid pointer value causes a system-generated runtime fault

So, after a delete ptr;, ptr's value becomes a invalid pointer value, and using this value has implementation-defined behavior. However, it doesn't say that ptr's value is allowed to change.

It might be a philosophical question, how can one decide that a value has changed, if one cannot use its value?

6.9:

For any object (other than a base-class subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes (4.4) making up the object can be copied into an array of char, unsigned char, or std::byte (21.2.1).43 If the content of that array is copied back into the object, the object shall subsequently hold its original value.

So, it seems, that it is valid to memcpy an invalid pointer value into a char array (depending on which statement is "stronger", 6.7 or 6.9. To me, 6.9 seems stronger).

This way, I can detect, that the pointer value has been changed by delete: memcpy the pointer's value before and after the delete to char array, then compare them.

So, as I understand, 6.7 doesn't grant that delete is allowed to modify its parameter.

Is delete allowed to modify its parameter?

Check out the comments here: https://mcmap.net/q/426942/-why-compilers-do-not-assign-null-to-pointer-variable-automatically-after-deleting-dynamic-allocated-memory-duplicate


Here's an unlikely, but still possible real-world code, where this matters:

SomeObject *o = ...; // We have a SomeObject
// This SomeObject is registered into someHashtable, with its memory address
// The hashtable interface is C-like, it handles opaque keys (variable length unsigned char arrays)

delete o;

unsigned char key[sizeof(o)];
memcpy(key, &o, sizeof(o)); // Is this line OK? Is its behavior implementation defined?
someHashtable.remove(key, sizeof(key)); // Remove o from the hashtable

Of course, this snippet can be reordered, so it becomes a surely valid code. But the question is: is this a valid code?


Here's a related train of thought: suppose, that an implementation does define what footnote describes:

copying an invalid pointer value causes a system-generated runtime fault

6.9 guarantees that I can memcpy() any value. Even an invalid one. So in this theoretical implementation, when I memcpy() the invalid pointer value (which should succeed, 6.9 guarantees that), in a sense, I don't use the invalid pointer value, but only its underlying bytes (because it would generate a runtime fault, and 6.9 doesn't allow it), so 6.7 doesn't apply.

Gliwice answered 17/7, 2017 at 16:57 Comment(33)
"It might be a philosophical question, how can one decide that a value has changed, if one cannot use its value?" the paragraph above that sentence just states that you may not dereference the pointer, but something like delete p; if (p==someOtherPOinter){} should be fineIberian
....ups i was wrong... missed the "implementation defined" part of that quoteIberian
@tobi303 That "implementation-defined" part is what allows implementations to nullify the pointer.Tubman
I was asking the exact same question (not here but to myself and my friend google) and iirc the only answer I found was that quote from Stroustrup. Now I am a bit surprised that the standard seems to be not soo explicit as the quote suggestsIberian
@Barmar: Why? As I understand, it only makes the pointer's value "invalid". It doesn't change it, just it becomes invalid. For example, I can assign a lot of pointers to a memory area which get deleted. Then these pointers' value won't change. The only change is that these pointers' values now considered invalid.Gliwice
The way I read the above, nothing explicitly prevents you from looking at a pointer's value after it's been deleted (the memory pointed to has been freed), so it seems that you don't have to do memcpy - just compare, cast to appropriate typed integer, or whatever.Lib
@Gliwice Since the result of using it is implementation-defined, the implementation can define that if (p == nullptr) is true for this invalid value.Tubman
@500-InternalServerError: "Any other use of an invalid pointer value has implementation-defined behavior." I think this statement forbids to use the pointer's value.Gliwice
@Barmar: sure. But in your example, p's value is not necessarily changed. Just the implementation says that p==nullptr is true, if p has invalid pointer value. This is different, doesn't mean that p's value have changed.Gliwice
@Gliwice Then I defer to the "as if" rule. If all operations can act the same as if the value had been changed, the implementation is allowed to change it.Tubman
@Barmar: that's the point, because not all operations acts the same. If I memcpy it, I can see that p has changed, which is not allowed anywhere in the standard (at least, as I checked it. It is huge, maybe I missed it).Gliwice
With the ARM (de facto standard before 1998) one couldn't delete a const object. This changed with the 1998 standardization. It's therefore conceivably possible that other things also changed, such as wording about changing the value of an lvalue pointer expression argument. Still this is of no practical utility. Accessing the value of a pointer after its pointee has been destroyed is Undefined Behavior anyway.Deettadeeyn
"So, as I understand, 6.7 doesn't grant that delete is allowed to modify its parameter.". I don't see how you come to that conclusion. Memcopying the pointer after and before the delete and then comparing, is not the same as memcopying the pointer before deletion and then copying it back into the pointer.Bulrush
"As I understand, it only makes the pointer's value "invalid".". Yes, and if the value is invalid, then "Any other use of an invalid pointer value has implementation-defined behavior.". I don't see where the wording leaves any room for interpretation here.Bulrush
"If I memcpy it, I can see that p has changed" - that's fine, because "Any other use of an invalid pointer value has implementation-defined behavior". You use memcpy to access part of the value, and accessing the value has implementation-defined behavior. So why would you expect the value to remain the same as before?Bulrush
@JohannesSchaub-litb: yes, I understand that. And maybe you are right. But, in a sense, I don't use invalid pointer value (this is highly arguable, of course). I use the underlying representation of it, the bytes that makes this pointer value. I pass a pointer to this value to memcpy. And memcpy doesn't know about anything, it just copies bytes.Gliwice
@Gliwice What rule forbids changing the internal bits of an int? As far as I know, the implementation is even allowed to make int a = 0; /* test bits of 'a' now */; /* test bits of 'a' now*/ have two different bits each time.Bulrush
@JohannesSchaub-litb: good question :) I don't know the standard at this level. It would be a surprise for me, if this were allowed, though. I'd expect that the bytes don't change of an int, if its value is not changed.Gliwice
You seem to be conflating the delete() method with the delete operator. The delete() method can do anything it likes with its parameter, to answer your actual question. It is received by value, so changes inside the method do not propagate outside. The delete operator could zero its operand, as suggested by Stroustrup. The memcpy() operations are legal, as the variable itself remains in existence and still has an address. Basically unclear what you're asking.Millisent
@EJP There is no "delete method", I guess you mean the operator delete() function. But this is exactly what is referred to by "the deallocation function" in `[basic.stc.dynamic.deallocation]/4. (The delete operator invokes destructor then calls deallocation function).Illustrious
@M.M. Yes, that's what I mean. There's a confusion here between operators and functions, and between operands and parameters. Operators have operands: functions have parameters.Millisent
@EJP: "The delete operator could zero its operand, as suggested by Stroustrup". That is the question: where does the standard say so? I don't find this explicitly in the standard. It talks about accessing the invalid pointer value is impl-defined. There's nothing about modifying it.Gliwice
@Gliwice The implementation could modify the bits stored in the storage for the pointer variable, and it would conform to the standard (if you disagree then cite which rule would be violated)Illustrious
@EJP In my earlier comment I accidentally wrote "the delete operator" when I meant "the delete expression". There is no delete operator; there's the delete expression, and the operator delete() function (which is a deallocation function despite its syntax). The expression following the keyword delete in the delete expression doesn't have a specific name but it's clear that OP meant to refer to that by "parameter" in the questionIllustrious
@M.M: I think the other way around :) If the standard doesn't allow it explicitly, then it's forbidden. But maybe there's something in the standard which says that I shouldn't think this way (I only know the standard cursorily)Gliwice
@Gliwice the standard specifies the observable behaviour of a program , there are no constraints on how it uses physical storage or what bits mean what in the hardware etc., so long as the observable behaviour matches what is specifiedIllustrious
@M.M: yep. And presumably you're right on the point that the question is: "can delete ptr; change the representation of ptr?". So, in the standard, is it allowed for any variable to change the representation, while its value is not changed? It is the same question that Johannes Schaub asked in the comments above. If it is not allowed, then I don't think that delete is allowed to do that (because what is special about delete? Why would it be possible for delete to do that?). If repr is allowed to change any time (that would be strange to me, to be honest), then we found the answer.Gliwice
@Gliwice yes, as mentioned in my answer it's the value that matters and there is not a 1-1 correspondence (in either direction) between values and representations .Usually there is of course for economy of memory usage, but an example is negative zeros for 1's complement integers, another broad case is unused bits in a type, and I interpret the part we're talking about on this question as saying that if a pointer has invalid value then that is independent of representation, i.e. no matter what the rep. is, it's still an invalid value and will remain so until assigned a valid valueIllustrious
@M.M: that's okay, but is the representation is allowed to change? If yes, where is it allowed in the standard? I mean not just the delete case, but generally?Gliwice
The standard only says that variables retain their values unless otherwise specified, it doesn't say they retain their representationsIllustrious
@M.M: so you say, that for int a = 0; char b[sizeof(int)]; memcpy(b, &a, sizeof(int)); if (memcmp(b, &a, sizeof(int)) { printf("differ\n"); } it is possible that "differ" will be printed? That's quite unexpected...Gliwice
@Gliwice I think it is technically permitted to give differ but no sane implementation would do that. The standard can't protect against Machiavelli. The bytes that make up an int are not char objects (so the guarantee about objects retaining their value doesn't apply on a byte by byte basis), and as far as I can tell, the standard doesn't actually say that there must be a relation between the result of aliasing one byte of an int, and the value of the int. The C++ memory model has various deficiencies, some much greater than this, a lot of it comes down to "it's meant to work normally"Illustrious
@M.M: I've asked thisGliwice
I
14

Before the deletion, ptr's value was valid. After the deletion, the value was invalid. Therefore the value changed. Valid values and invalid values are mutually exclusive -- a value cannot be simultaneously valid and invalid.

Your question has a basic misconception; you're conflating these two different concepts:

  • The value of a variable
  • The representation of a variable in memory.

There isn't a one-to-one correspondence between these two things. The same value may have multiple representations, and the same representation may correspond to different values.


I think the gist of your question is: can delete ptr; change the representation of ptr?. To which the answer is "Yes". You could memcpy the deleted pointer into a char array, inspect the bytes, and find them all to be zero-valued bytes (or anything else). This is covered in the standard by C++14 [basic.stc.dynamic.deallocation]/4 (or C++17 [basic.stc]/4):

Any other use of an invalid pointer value has implementation-defined behavior.

It's implementation-defined and the implementation could define that inspecting the bytes gives bytes with value zero.


Your code snippet relies on implementation-defined behaviour. "Valid code" isn't terminology used by the Standard, but the code might not remove the intended item from the hash table.

As alluded to by Stroustrup, this is an intentional design decision. An example usage would be a compiler in debug mode setting deleted pointers to a particular representation, so that it can raise a runtime error if a deleted pointer is subsequently used. Here's an example of that principle in action for uninitialized pointers.

Historical note: In C++11 this case was undefined, rather than implementation-defined. So the behaviour of using a deleted pointer was identical to the behaviour of using an uninitialized pointer. In the C language, freeing memory is defined as putting all pointers to that memory into the same state as an uninitialized pointer has.

Illustrious answered 20/8, 2017 at 21:42 Comment(17)
A given value certainly can and does become invalid as of a call. A pointer variable does not have to change for its value to become invalid. Also you are confusing implementation behaviour with specified (possibly implementation-defined) behaviour.Black
@Black I am saying that going from "the pointer variable has a valid value" to "the pointer variable has an invalid value" tautologically means the value changed. (I think you are making the same misconception I pointed out in my answer; the representation might not have changed but the value did).Illustrious
Please explain further what you meant by your last sentenceIllustrious
I am saying that 'I am saying that going from "the pointer variable has a valid value" to "the pointer variable has an invalid" value tautologically means the value changed" ' is wrong, because the value itself becomes invalid (not dereferenceable or passable) whether or not the variable continues to hold that value.Black
Re my last sentence: Nothing is needed to describe the semantics other than the C++ object/execution model, ie lvalues identifying locations/objects holding values. That does involve some (specified & implementation-dependent) representations for values, but within the C++ abstract machine. A hypothetical implementation can illustrate but cannot justify because it begs the spec. From the entirety of your answer you seem to know this but I suspect reference to implementation in the earlier parts might mislead the OP.Black
@Black when deallocation happens, all pointer values which referred to any part of the freed storage become invalid values, that includes values stored in variables. See [basic.stc.dynamic.deallocation]/4. It is not just the particular value that was the "parameter" to delete.Illustrious
Sorry but I have no idea what you are talking about in your latest commentIllustrious
I don't see what that has to do with anything I wrote. "become invalid values" doesn't mean values somehow change, much less that they change in some implementation you hypothesize that the execution model doesn't support; it means the allocated pointer values are now considered invalid.Black
"become" implies changing. Do you reject my assertion that going from valid to invalid is a change? If so then we can't really communicate further as that is, to me, a basic property of the concept "change". (NB. I think this is a moot point anyway, as I believe OP is really asking about whether the representation of ptr can change).Illustrious
We seem to disagree. I am saying that "becomes invalid" is a change in status as defined in the rest of the paragraph; what "changes" is how the program acts, compared to before, when you use those (same) values.Black
@Black How do you incorporate the fact that the representation may change, into your scheme? E.g. let's say that the implementation makes delete ptr; set ptr to all-bits-zero (which is permitted by the standard as explained in the second section of my answer). Are you claiming that is actually not a change in value too?Illustrious
It's not clear whether you mean "setting" a reference/constant to zero or setting a variable/object with address/lvalue ptr to 0. Either way, I have said nothing about that. I would call that a change in value. But that's nothing to do with "value becomes invalid".Black
@M.M: my main problem is "the values of all pointers representing the address of any part of that region of storage become invalid pointer values" could mean that the value doesn't change, but the value is interpreted as invalid. Furthermore, about accessing the invalid value: footnote says: "Some implementations might define that copying an invalid pointer value causes a system-generated runtime fault". But I yet think that I can access the value with memcpy, as 6.9 warrants this. So, with memcpy, I don't access pointer value in an implementation specified way for accessing invalid ptr value.Gliwice
@M.M: I mean: suppose that an implementation does indeed specify that accessing an invalid pointer value generates a runtime fault. Does this mean (contrary to 6.9), I cannot access its value with memcpy? If it doesn't mean that, then with memcpy, I don't use invalid pointer value (just the underlying repr), so implementation specified rule doesn't apply hereGliwice
@Gliwice Well, I think you have identified a place where the standard text is less than ideal. I will make some changes to my answer later on, to address that point specificallyIllustrious
I understand the philosophical point you are trying to make (and I agree with it), but the wording is really unhelpful. To say "the value has changed" is very, very, confusing. It would help enormously, if your third sentence was "Therefore the value changed (although the bit representation in memory may not have done)." Alternatively, move your second paragraph to be first.Proverbs
I agree that "gist of your question is: can delete ptr; change the representation of ptr". The answer to this question is ambiguous to me, however. There's nothing in the standard which specifically allows delete to change representation of its argument, so it should be forbidden. I think, it could be allowed only in the case when it is allowed for any variable (except char based types) to suddenly change representations (even when there is no value change at all). I will accept this answer, because I think this is the best we can say about the subject (maybe the standard should clarify this).Gliwice
O
2

The context in which you found the statement from Stroustrup, is available under Stroustrup, delete zero

Stroustrup let you consider

delete p;
// ...
delete p;

After the first delete, pointer p was invalid. The second delete is wrong, but it would have no effect if p was set to 0 after the first delete.

Stroustrups idea was to compile it as something like

delete p; p = 0;
// ...
delete p;

delete itself is not able to zero out the pointer since it passed void * but not void *&

However, I find zero out p doesn't help very much as they may exist other copies of that pointer which may accidently deleted, too. A better way is to use the different type of smartpointers.

Spec 6.7

Says that any pointer with the address of pointer p will be invalid (in an implementation defined way) after a delete p. It says nothing about changing the pointer address, neither it is allowed nor it is forbidden.

Spec 6.9

The prerequisit of 6.9 is a object (valid or not). This spec does not apply here since p (the address) is no more valid after delete and thatfore does NOT point to an object. So there is no contradiction, and any discussion whether 6.7 or 6.9 is stronger is invalid.

The spec requires also to copy the bytes back to the original object location, which your code does not, and would not be able too, because the original object has been deleted.


However, I see no reason to pack a pointer address into a char array and pass it. And pointers have always the same size in an certain implementation. Your code is just a cumbersome version of:

SomeObject *o = ...;

void *orgO = o;
delete o;

someHashtable.remove(orgO);
// someHashtable.remove(o); o might be set to 0

However, this code still looks strange. To get an object from the hash table you need the pointer to that object. Why not directly use the pointer directly??

A hash table should help to find objects by some invariant values of the objects. That is not your application of hash table

Did you intented to have a list of all valid instances of SomeObject?

Your code is invalid cause, according to Stroustrup, the compiler is allowed to set p to zero. If this happened your code will crash

Osgood answered 22/8, 2017 at 10:22 Comment(2)
My code doesn't dereference the pointer. I think you completely misunderstood the subject. It is not about accessing the freed memory, but accessing the pointer itself.Gliwice
OK, i see it nowOsgood
B
2

Indirection through an invalid pointer value and passing an invalid pointer value to a deallocation function have undefined behavior. Any other use of an invalid pointer value has implementation-defined behavior.

So, after a delete ptr;, ptr's value becomes a invalid pointer value, and using this value has implementation-defined behavior.

The standard is saying that the pointer value passed "becomes invalid", ie its status has changed so that certain calls become undefined and the implementation can treat it differently.

The language is not very clear, but here is the context:

6.7 Storage duration
4 When the end of the duration of a region of storage is reached, the values of all pointers representing the address of any part of that region of storage become invalid pointer values (6.9.2). Indirection through an invalid pointer value and passing an invalid pointer value to a deallocation function have undefined behavior. Any other use of an invalid pointer value has implementation-defined behavior.

6.9.2 Compound types
Every value of pointer type is one of the following:
(3.1) — a pointer to an object or function (the pointer is said to point to the object or function), or
(3.2) — a pointer past the end of an object (8.7), or
(3.3) — the null pointer value (7.11) for that type, or
(3.4) — an invalid pointer value.

It is values of type pointer that are or are not invalid, and they "become" so according to the progress of excution of a program on the C++ abstract machine.

The standard is not talking about changes to what value is held by the variable/object addressed by an lvalue or changes to the association of a symbol with a value.

C++ explicitly allows an implementation of delete to zero out an lvalue operand, and I had hoped that implementations would do that, but that idea doesn't seem to have become popular with implementers.

Separately from this, Stroustrup is saying that if an operand expression was a modifiable lvalue, ie an operand expression was the address of a variable/object holding a pointer value that gets passed, after which the status of that value is "invalid", then the implementation can set the value held by that variable/object to zero.

However, it doesn't say that ptr's value is allowed to change.

Stroustrup is being informal by talking about what an implementation can do. The standard defines how an abstract C++ machine can/cannot/may behave. Here Stroustrup is talking about a hypothetical implementation that looks like that machine. A "ptr's value" is "allowed to change" because the defined and undefined behaviour doesn't let you find out what that value is as of deallocation, and the implementation-defined behaviour can be anything, so it can be that the variable/object holds a different value.

It does not make sense to talk about a value changing. You can't "zero out" a value; you can zero out a variable/object, and that's what we mean when we say "zero out" an lvalue--zero out the variable/object it references/identifies. Even if you stretch "zero out" to include associating a new value with a name or literal, the implementation can do this, because you cannot "use" the value at runtime via the name or literal to find out whether it is still associated with the same value.

(However, since all one can do with a value is "use" it in a program by passing an lvalue identifying a variable/object holding it to an operator or by passing a reference or constant denoting it to an operator, and an operator can act as if a different value was passed, I guess you could reasonably informally sloppily capture that as "values changing value" in the implementation.)

If the content of that array is copied back into the object, the object shall subsequently hold its original value.

But copying it is using it so copying it is implementation-defined once it is "invalid". So calling a program that would normally copy it is implementation-defined. This is made clear by the footnote that gives the example that

Some implementations might define that copying an invalid pointer value causes a system-generated runtime fault

Nothing does what it normally does as of undefined/implemenation-defined behaviour. We use the normal behaviour to determine a sequence of changes to an abstract machine, and if an implementation-defined state change arises then things act like the implementation defines them to act, not the way they normally do. Sadly the meaning of "use of" a value is not made clear. I don't know why you think 6.9 "guarantees" anything more or less re memcpy than anywhere re anything, which after an undefined/implementation-defined state is nothing.

Black answered 25/8, 2017 at 8:5 Comment(15)
To me, these are not that obvious. That footnote (invalid pointer value causes runtime fault) conflicts with 6.9, which guarantees that even an invalid value can be copied. How do you resolve this?Gliwice
6.9 explicitly mentions invalid values: "whether or not the object holds a valid value of type T". So it seems that memcpy isn't considered "use of". Or at least this is the only explanation I can give. This is how this conflict can be resolved, at least.Gliwice
I agree with you on the part that "becomes invalid" doesn't necessarily mean that that value is changed. But other parts of the accepted answer seems to be right for me.Gliwice
Regardless of the 6.9 issue, Stroutrup is talking about zeroing out a variable/object. Also, I can't tell from your question what you think is being "zeroed out".Black
I think he talks about zeroing the pointer itself (or what do you mean by your comment?), that's why the lvalue requirement.Gliwice
"The pointer itself" is unclear. The value passed? That's a value, and as I explain in my answer it does not make sense to talk about "zeroing out" a value. You can "zero out" a variable/object. You can associate a name/literal with a value; you could sloppily use "zero out" to mean associate a new value with one.Black
I don't really see what you mean. Is allowed for delete p; to change p's value (the pointer itself)? Or p's underlying representation?Gliwice
In which point of view are representations irrelevant? Is p's repr allowed to change? I think this question is unambiguous.Gliwice
Sorry, I don't follow you. If it is irrelevant in all respects, then what is the answer to the question?Gliwice
You don't seem to understand how the standard specifies what programs do to an abstract C++ machine. Objects have values that have bit representations but I don't know why you think representations matter here. I suspect you are using "representation" for "value of an object" but I can't tell. If so, I don't know what you think a representation is a representation of. Your writing is not clear. I'm editing an earlier comment about what you think is "changing".Black
You are still unclear. Please use C++ terms, unambiguously. As in my answer. "p" is a name. If it is not a ref then we colloquially say it is/names a (const or modifiable) "variable" with associated lvalue &p that is the address of an object holding value (p).delete p passes lvalue (p). What kind(s) of p are you imagining? What "changes" to what? (Stroustrup means, modifiable variable p's held value is passed & p holds 0 after. This has nothing to do with 6.9.)Black
Please look at the example I given in the question. For this concrete example i the comments, p is a pointer variable. For example, int *p; p = <some_value_from_somewhere>; delete p;. Is delete allowed to change p's underlying bytes?Gliwice
As I said clearly in my answer, yes it can. Again: An implementation can assign a value as part of the delete's effect on the abstract C++ machine because it cannot affect the observable behaviour of a conforming implementation-independent program. Even if you consider memcpy non-"use", you can't thereafter use it in an implementation-independent way to affect observable behaviour.Black
I'm not saying that the underlying bytes are implementation-independent. The question is, are these bytes allowed to change? But, the real, more general question is this. It think we can agree that (maybe), that this question is boils down to the linked question. If the answer to the linked question is "no", then I don't think that delete is allowed to change the bytes either. Simply because the standard nowhere allows it.Gliwice
To me, the current wording of the standard means that memcpy'ing an invalid pointer value is not considered "usage", simply because it would violate 6.9.Gliwice
C
1

In order for a delete function to update the pointer, it needs to know the address of this pointer and also do the update. This would require extra memory, few extra operations and a compiler support. Looks more or less trivial in your example.

Now imagine a chain of functions which pass the pointer to each other in arguments and only the last one will really delete. Which pointers to update in such a case? The last one? All? For the latter one would need to create a dynamic lists of pointers:

Objec *o = ...
handle(o);
void handle(Object *o){
   if (deleteIt) doDelete(0);
   else doSomethingElseAndThenPossiblyDeleteIt(o);
}
void doDelete(Object *o) {
    delete o;
}

So, philosophically if the delete would be allowed to modify its parameter, it would open a can of warms reducing program efficiency. So, it is not allowed and i hope that it will never be. The undefined behavior is probably the most natural thing in those cases.

As for the memory contents, unfortunately i saw too many errors where a deleted memory gets overwritten after the pointer was deleted. And... it works ok till a moment comes. Since the memory is marked as free it get reused by other objects eventually with very uninteresting consequences and a lot of debugging. So, philosophically again, c++ is not an easy language to program with. There are other tools which could catch those issues, without any language support.

Cutoff answered 22/8, 2017 at 1:7 Comment(4)
It doesn't have to modify the parameter, it's just an option. IMO it'd be natural to use in debug mode.Illustrious
@Illustrious There are debugging and linting tools around which can catch those issues today without this.Cutoff
@Serge: you answered this question from the practice viewpoint. But this question is about the standard. When you say "So, it is not allowed and i hope that it will never be", it is backed up with efficiency reasons. But I'd like to have quotes from the standard, and interpretations of them.Gliwice
@Gliwice i guess my point was that i order top allow 'dlelete' to modify its pointer, the standard would have to provide for the mechanism of passing it to the function and the ways to handle chain assignments and other situations. It definitely does not do it.Cutoff

© 2022 - 2024 — McMap. All rights reserved.