Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[expr.delete] p7 The time of calling a deallocation function #4850

Open
xmh0511 opened this issue Aug 31, 2021 · 8 comments
Open

[expr.delete] p7 The time of calling a deallocation function #4850

xmh0511 opened this issue Aug 31, 2021 · 8 comments
Labels
cwg Issue must be reviewed by CWG. not-editorial Issue is not deemed editorial; the editorial issue is kept open for tracking.

Comments

@xmh0511
Copy link
Contributor

xmh0511 commented Aug 31, 2021

If the value of the operand of the delete-expression is not a null pointer value, then:

  • [...]
  • Otherwise, if the allocation was extended or was provided by extending the allocation of another new-expression, and the delete-expression for every other pointer value produced by a new-expression that had storage provided by the extended new-expression has been evaluated, the delete-expression shall call a deallocation function. The value returned from the allocation call of the extended new-expression shall be passed as the first argument to the deallocation function.
  • Otherwise, the delete-expression will not call a deallocation function.

Consider this example

struct Container{
   char memory[2];
};
auto ptr0 = new Container;  //#0
auto ptr1 = new char;  // #1
auto ptr2 = new char;  //#2
delete ptr1;  //#3
delete ptr2;  //#4
delete ptr0;  //#5

Assume the new-expression at #0 has been extended to provide the storage for #1 and #2. Note the emphasized wording in the second bullet, since there are only two new-expression that use the allocation provided by #0, hence at this point at #4, could we say the delete-expression for every other pointer value(...) has been evaluated? So, the deallocation function shall be called at #4? At the point of #5, the second bullet is also satisfied, hence it again call the deallocation function? Obviously, it does not make sense however it is what the second bullet saying.

I think the second bullet is intend to cover the following case

auto ptr0 = new Container;  //#0
auto ptr1 = new char;  // #1
auto ptr2 = new char;  //#2
delete ptr1;  //#3
delete ptr0;  //#5
delete ptr2;  //#4

This example is based on the first by adjusting the order of the delete-expression whose operand is produced by the extended allocation. The second bullet can work fine in this example, since #4 has not been evaluated, hence #5 cannot invoke the deallocation function, it's the responsibility of #4. However, as aforementioned, the second bullet seems not good at the first example.

@JohelEGP
Copy link
Contributor

Otherwise, if the allocation was extended or was provided by extending the allocation of another new-expression, and the delete-expression for every other pointer value produced by a new-expression that had storage provided by the extended new-expression has been evaluated, the delete-expression shall call a deallocation function. The value returned from the allocation call of the extended new-expression shall be passed as the first argument to the deallocation function.

The storage for #0 was also provided by this extended new-expression, so it's accounted for, too.

@xmh0511
Copy link
Contributor Author

xmh0511 commented Aug 31, 2021

The storage for #0 was also provided by this extended new-expression, so it's accounted for, too.

If you mean the new-expression at #0 provides the storage for itself, it seems impossible, since we should obey [expr.new] p14

The implementation may extend the allocation of a new-expression e1 to provide storage for a new-expression e2 if the following would be true were the allocation not extended:

the evaluation of e1 is sequenced before the evaluation of e2, and

The evaluation of an expression cannot be sequenced before that of itself.

@JohelEGP
Copy link
Contributor

Otherwise, if the allocation was extended or was provided by extending the allocation of another new-expression, and the delete-expression for every other pointer value produced by a new-expression that had storage provided by the extended new-expression has been evaluated, the delete-expression shall call a deallocation function. The value returned from the allocation call of the extended new-expression shall be passed as the first argument to the deallocation function.

But it does produce a pointer value, which is deleted at #5. That is what is counted.

@xmh0511
Copy link
Contributor Author

xmh0511 commented Aug 31, 2021

However, the pointer value that is produced by a new-expression has another restriction, which is

that had storage provided by the extended new-expression

As per [expr.new#14], e1 cannot provide storage for itself. Specifically, if we say the delete-expression for ptr0 produced by a new-expression(at #0) that had storage provided by the extended new-expression(at #0) has been evaluated, we claim that extend the allocation of a new-expression(at #0) e1 to provide storage for a new-expression(at #0).

@jensmaurer
Copy link
Member

True, [expr.new] p14 is not applicable for the new-expression that ends up calling the allocation function. However, the understanding is that the allocation function invoked by a new-expression does provide storage for that very new-expression (and possibly for others, as discussed in p14).

@xmh0511
Copy link
Contributor Author

xmh0511 commented Aug 31, 2021

However, the understanding is that the allocation function invoked by a new-expression does provide storage for that very new-expression (and possibly for others, as discussed in p14).

Yes, however, it's impossible that the new-expresion that has been extended provides the storage for itself as per [expr.new#14.1], except that we say

the evaluation of e1 is sequenced before the evaluation of e2, or e1 is e2, and

@jensmaurer
Copy link
Member

jensmaurer commented Aug 31, 2021

We can certainly say in [expr.new] p10 "A new-expression may obtain storage for the object by calling an allocation function (6.7.5.5.2); the allocation is said to provide storage for the new-expression."

There are simply several options how to provide storage for a new-expression; one is by calling "operator new" and another is by extending an allocation per the p14 rules.

However, I'm hesitant to editorially extend the use of "provides storage" here some more, because [intro.object] p3 uses "provides storage" for a slightly different purpose.

@jensmaurer jensmaurer added the decision-required A decision of the editorial group (or the Project Editor) is required. label Aug 31, 2021
@xmh0511
Copy link
Contributor Author

xmh0511 commented Jan 18, 2022

Since [expr.new] p15 says

The implementation may extend the allocation of a new-expression e1 to provide storage for a new-expression e2.

Hence, to be consistent, [expr.delete] p7 should use the precise utterance

If the value of the operand of the delete-expression is not a null pointer value, then:

  • [...]
  • Otherwise, if the allocation was extended or was provided by extending the allocation of another new-expression, and the delete-expression for every other pointer value produced by a new-expression that had storage provided by the (allocation of ) the extended new-expression has been evaluated, the delete-expression shall call a deallocation function. The value returned from the allocation call of the extended new-expression shall be passed as the first argument to the deallocation function.

Not the extended new-expression provides the storage for a new-expression, instead, the allocation of the extended new-expression provides that storage.

With the fix: A new-expression may obtain storage for the object by calling an allocation function (6.7.5.5.2); the allocation is said to provide storage for the new-expression.

This issue will be ok.

@tkoeppe tkoeppe added the cwg Issue must be reviewed by CWG. label Jun 12, 2023
@jensmaurer jensmaurer added not-editorial Issue is not deemed editorial; the editorial issue is kept open for tracking. and removed decision-required A decision of the editorial group (or the Project Editor) is required. labels Jun 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cwg Issue must be reviewed by CWG. not-editorial Issue is not deemed editorial; the editorial issue is kept open for tracking.
Projects
None yet
Development

No branches or pull requests

4 participants