Date: Sun, 15 Oct 2023 10:22:17 -0700
On Sun, Oct 15, 2023, 07:01 Peter Sommerlad (C++) via Core <
core_at_[hidden]> wrote:
> Hi,
>
> I understand while in general delete baseptr; is UB when the base
> doesn't have a virtual destructor (or a destroying operator delete that
> does the right thing).
>
> However, I wonder if in the case of trivial destructors for both base
> and derived and/or when sizeof(base) == sizeof(derived) there is a need
> for making deleting via a base pointer undefined behavior.
>
You would also need to require that the alignment is also the same, and
that there's no class-specific operator delete -- ideally, along with any
other properties we might use in the future when choosing how to construct
an `operator delete` call. (Note that if we'd had the rule you're
suggesting in place from the start, we would have been unable to add
aligned allocation without breaking compatibility.)
The situation where such constructs occur is common with mix-in types or
> derived classes that act as adapters to the base class, e.g., by
> providing additional interfaces, for example.
>
> Especially with the extended aggregate capabilities it can be attractive
> not to introduce a protected destructor in the base class to prevent
> derived-to-base pointer conversions.
>
> So my question is, can we reduce the risk of undefined behavior by
> changing [expr.delete] p.3
>
> from
>
> "In a single-object delete expression, if the static type of the object
> to be deleted is not similar (7.3.6) to its dynamic type and the
> selected deallocation function (see below) is not a destroying operator
> delete, the static type shall be a base class of the dynamic type of the
> object to be deleted and the static type shall have a virtual destructor
> or the behavior is undefined. In an array delete expression, if the
> dynamic type of the object to be deleted is not similar to its static
> type, the behavior is undefined."
>
> to
> In a single-object delete expression, if the static type of the object
> to be deleted is not similar (7.3.6) to its dynamic type and the
> selected deallocation function (see below) is not a destroying operator
> delete, the static type shall be a base class of the dynamic type of the
> object to be deleted and the static type shall have <ins>either</ins> a
> virtual destructor <ins>or both the static type and the dynamic type
> shall have a trivial destructor and have the same size, otherwise</ins>
> <del>or</del> the behavior is undefined. In an array delete expression,
> if the dynamic type of the object to be deleted is not similar to its
> static type, the behavior is undefined.
>
>
> Does it make sense to propose such a change?
>
> Regards
> Peter.
>
> --
> Peter Sommerlad
>
> Better Software: Consulting, Training, Reviews
> Modern, Safe & Agile C++
>
> peter.cpp_at_[hidden]
> +41 79 432 23 32
> _______________________________________________
> Core mailing list
> Core_at_[hidden]
> Subscription: https://lists.isocpp.org/mailman/listinfo.cgi/core
> Link to this post: http://lists.isocpp.org/core/2023/10/14957.php
>
core_at_[hidden]> wrote:
> Hi,
>
> I understand while in general delete baseptr; is UB when the base
> doesn't have a virtual destructor (or a destroying operator delete that
> does the right thing).
>
> However, I wonder if in the case of trivial destructors for both base
> and derived and/or when sizeof(base) == sizeof(derived) there is a need
> for making deleting via a base pointer undefined behavior.
>
You would also need to require that the alignment is also the same, and
that there's no class-specific operator delete -- ideally, along with any
other properties we might use in the future when choosing how to construct
an `operator delete` call. (Note that if we'd had the rule you're
suggesting in place from the start, we would have been unable to add
aligned allocation without breaking compatibility.)
The situation where such constructs occur is common with mix-in types or
> derived classes that act as adapters to the base class, e.g., by
> providing additional interfaces, for example.
>
> Especially with the extended aggregate capabilities it can be attractive
> not to introduce a protected destructor in the base class to prevent
> derived-to-base pointer conversions.
>
> So my question is, can we reduce the risk of undefined behavior by
> changing [expr.delete] p.3
>
> from
>
> "In a single-object delete expression, if the static type of the object
> to be deleted is not similar (7.3.6) to its dynamic type and the
> selected deallocation function (see below) is not a destroying operator
> delete, the static type shall be a base class of the dynamic type of the
> object to be deleted and the static type shall have a virtual destructor
> or the behavior is undefined. In an array delete expression, if the
> dynamic type of the object to be deleted is not similar to its static
> type, the behavior is undefined."
>
> to
> In a single-object delete expression, if the static type of the object
> to be deleted is not similar (7.3.6) to its dynamic type and the
> selected deallocation function (see below) is not a destroying operator
> delete, the static type shall be a base class of the dynamic type of the
> object to be deleted and the static type shall have <ins>either</ins> a
> virtual destructor <ins>or both the static type and the dynamic type
> shall have a trivial destructor and have the same size, otherwise</ins>
> <del>or</del> the behavior is undefined. In an array delete expression,
> if the dynamic type of the object to be deleted is not similar to its
> static type, the behavior is undefined.
>
>
> Does it make sense to propose such a change?
>
> Regards
> Peter.
>
> --
> Peter Sommerlad
>
> Better Software: Consulting, Training, Reviews
> Modern, Safe & Agile C++
>
> peter.cpp_at_[hidden]
> +41 79 432 23 32
> _______________________________________________
> Core mailing list
> Core_at_[hidden]
> Subscription: https://lists.isocpp.org/mailman/listinfo.cgi/core
> Link to this post: http://lists.isocpp.org/core/2023/10/14957.php
>
Received on 2023-10-15 17:22:30