Stl: unable to override functions in recent exception / xmemory changes

Created on 23 Oct 2019  路  3Comments  路  Source: microsoft/STL

previously, this function: https://github.com/microsoft/STL/blob/379e61781a38eafcff2bd2bc8a099ef5591594ba/stl/inc/xmemory#L28.. returned (size_t)( -1 ).

within the last few months, the function now calls into _Throw_bad_array_new_length which uses the _THROW macro and will result in code generation importing functions from MSVC libraries.

previously, a user was able to suppress generation of these exceptions by disabling them with compiler flags and specifying #define _HAS_EXCEPTIONS 0.

since these "new" throw functions already have a body defined, a user cannot override them with their own implementation. the other exception functions have a definition here: https://github.com/microsoft/STL/blob/53cdb9f8a85c2500077ccf0676619110340c03bf/stl/inc/xutility#L5092... which allow a user to provide their own implementation (and, resulting in strings and exception imports to be omitted).

are there any changes planned for this? a new way to get add your own implementation for exception handling? or have exception / xmemory actually listen to the _HAS_EXCEPTIONS preprocessor definition?

wontfix

Most helpful comment

Except as mandated by the Standard (for operator new etc.), we don't support replacing separately compiled functions in the STL.

At this time, _HAS_EXCEPTIONS=0 is mostly unsupported. We try to avoid breaking it gratuitously, but it's undocumented, not officially supported, and not really tested. We might overhaul it in the future to be a supported mode, but we have no concrete plans yet. Ultimately I think we want _THROW to become fastfail in _HAS_EXCEPTIONS=0 mode instead of whatever it does today.

In this case, the STL contains a number of header-only mentions of _THROW, in addition to our separately compiled helpers. (The separately compiled helpers were originally added to avoid circular header dependencies, not for user replacements.) Therefore, I don't believe that this change is a gratuitous break. The bad_array_new_length was done as part of implementing LWG-3038, although it mandated a length_error. As I explained to the Library Evolution Working Group:

An implementer veto is when the Working Paper tells us to do a thing, and then we don't do that thing, but instead do some other thing. We don't do this lightly - we reserve it only for the most dire of circumstances - e.g. when the WP's text is self-contradictory, unusably broken, or impossible to implement given our compatibility requirements.

In this case, we view throwing a non-bad_alloc-derived exception from allocate() as unusably broken, especially given the existence of a bad_alloc-derived exception that was more or less meant for this scenario. Our pre-existing behavior was that we clamped integer overflow to static_cast<size_t>(-1) and let that trigger plain bad_alloc; changing that to length_error would have been a runtime regression in functionality. Upgrading bad_alloc to bad_array_new_length is a compatible change.

This is now tracked by LWG-3237.

As your request is non-Standard, and I don't see anything else we can do here aside from overhauling _HAS_EXCEPTIONS=0 (which we may not be able to do in the VS 2019 release series due to binary compatibility), I believe this issue should be resolved as wontfix.

(Of course, because we're open-source now, you're free to take our codebase and modify it to suit your purposes.)

All 3 comments

FYI, defining/overriding anything but a limited set of things (like std::hash specializations) in namespace std is UB.

In this particular situation, it seems that the solution is to write your own allocator.

FYI, defining/overriding anything but a limited set of things (like std::hash specializations) in namespace std is UB.

In this particular situation, it seems that the solution is to write your own allocator.

if a user wants exceptions disabled, i feel as if they should be _disabled_ and not _somewhat disabled_.

is there even a way to fully overwrite the default allocator that standard containers use (like std::string, std::vector, etc) or must a user define these types manually with the new allocator?

Except as mandated by the Standard (for operator new etc.), we don't support replacing separately compiled functions in the STL.

At this time, _HAS_EXCEPTIONS=0 is mostly unsupported. We try to avoid breaking it gratuitously, but it's undocumented, not officially supported, and not really tested. We might overhaul it in the future to be a supported mode, but we have no concrete plans yet. Ultimately I think we want _THROW to become fastfail in _HAS_EXCEPTIONS=0 mode instead of whatever it does today.

In this case, the STL contains a number of header-only mentions of _THROW, in addition to our separately compiled helpers. (The separately compiled helpers were originally added to avoid circular header dependencies, not for user replacements.) Therefore, I don't believe that this change is a gratuitous break. The bad_array_new_length was done as part of implementing LWG-3038, although it mandated a length_error. As I explained to the Library Evolution Working Group:

An implementer veto is when the Working Paper tells us to do a thing, and then we don't do that thing, but instead do some other thing. We don't do this lightly - we reserve it only for the most dire of circumstances - e.g. when the WP's text is self-contradictory, unusably broken, or impossible to implement given our compatibility requirements.

In this case, we view throwing a non-bad_alloc-derived exception from allocate() as unusably broken, especially given the existence of a bad_alloc-derived exception that was more or less meant for this scenario. Our pre-existing behavior was that we clamped integer overflow to static_cast<size_t>(-1) and let that trigger plain bad_alloc; changing that to length_error would have been a runtime regression in functionality. Upgrading bad_alloc to bad_array_new_length is a compatible change.

This is now tracked by LWG-3237.

As your request is non-Standard, and I don't see anything else we can do here aside from overhauling _HAS_EXCEPTIONS=0 (which we may not be able to do in the VS 2019 release series due to binary compatibility), I believe this issue should be resolved as wontfix.

(Of course, because we're open-source now, you're free to take our codebase and modify it to suit your purposes.)

Was this page helpful?
0 / 5 - 0 ratings