Allow user to configure if free is allowed at runtime.

<!--
Thanks for contributing a merge request!

We recommend that first-time contributors read our [contribution guidelines](https://eigen.tuxfamily.org/index.php?title=Contributing_to_Eigen).

Before submitting the MR, please complete the following checks:
- Create one PR per feature or bugfix,
- Run the test suite to verify your changes.
  See our [test guidelines](https://eigen.tuxfamily.org/index.php?title=Tests).
- Add tests to cover the bug addressed or any new feature.
- Document new features.  If it is a substantial change, add it to the [Changelog](https://gitlab.com/libeigen/eigen/-/blob/master/CHANGELOG.md).
- Leave the following box checked when submitting: `Allow commits from members who can merge to the target branch`.
  This allows us to rebase and merge your change.

Note that we are a team of volunteers; we appreciate your patience during the review process.
-->

### Description
<!--Please explain your changes.-->

Allow user to configure if `free` is allowed at runtime.

Reverts to Eigen 3.4 behavior by default, where `free(...)` is allowed if `EIGEN_RUNTIME_NO_MALLOC` is defined but `set_is_malloc_allowed(true)`.  Adds a separate `set_is_free_allowed(...)` to explicitly control use of `std::free`.

### Reference issue
<!--
You can link to a specific issue using the gitlab syntax #<issue number>.
If the MR fixes an issue, write "Fixes #<issue number>" to have the issue automatically closed on merge.
-->

Fixes #2983.

### Additional information
<!--Any additional information you think is important.-->

Closes #2983

See merge request libeigen/eigen!2047

(cherry picked from commit 60122df698)
This commit is contained in:
Antonio Sánchez
2025-10-28 22:29:00 +00:00
committed by Antonio Sanchez
parent a9110bfc87
commit 691009cfa3

View File

@@ -91,6 +91,9 @@ namespace internal {
EIGEN_DEVICE_FUNC inline void check_that_malloc_is_allowed() {
eigen_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
}
EIGEN_DEVICE_FUNC inline void check_that_free_is_allowed() {
eigen_assert(false && "heap deallocation is forbidden (EIGEN_NO_MALLOC is defined)");
}
#elif defined EIGEN_RUNTIME_NO_MALLOC
EIGEN_DEVICE_FUNC inline bool is_malloc_allowed_impl(bool update, bool new_value = false) {
EIGEN_MALLOC_CHECK_THREAD_LOCAL static bool value = true;
@@ -101,10 +104,22 @@ EIGEN_DEVICE_FUNC inline bool is_malloc_allowed() { return is_malloc_allowed_imp
EIGEN_DEVICE_FUNC inline bool set_is_malloc_allowed(bool new_value) { return is_malloc_allowed_impl(true, new_value); }
EIGEN_DEVICE_FUNC inline void check_that_malloc_is_allowed() {
eigen_assert(is_malloc_allowed() &&
"heap allocation is forbidden (EIGEN_RUNTIME_NO_MALLOC is defined and g_is_malloc_allowed is false)");
"heap allocation is forbidden (EIGEN_RUNTIME_NO_MALLOC is defined and set_is_malloc_allowed is false)");
}
EIGEN_DEVICE_FUNC inline bool is_free_allowed_impl(bool update, bool new_value = false) {
EIGEN_MALLOC_CHECK_THREAD_LOCAL static bool value = true;
if (update == 1) value = new_value;
return value;
}
EIGEN_DEVICE_FUNC inline bool is_free_allowed() { return is_free_allowed_impl(false); }
EIGEN_DEVICE_FUNC inline bool set_is_free_allowed(bool new_value) { return is_free_allowed_impl(true, new_value); }
EIGEN_DEVICE_FUNC inline void check_that_free_is_allowed() {
eigen_assert(is_malloc_allowed() &&
"heap deallocation is forbidden (EIGEN_RUNTIME_NO_MALLOC is defined and set_is_free_allowed is false)");
}
#else
EIGEN_DEVICE_FUNC inline void check_that_malloc_is_allowed() {}
EIGEN_DEVICE_FUNC inline void check_that_free_is_allowed() {}
#endif
EIGEN_DEVICE_FUNC inline void throw_std_bad_alloc() {
@@ -161,7 +176,7 @@ EIGEN_DEVICE_FUNC inline void handmade_aligned_free(void* ptr) {
std::size_t offset = static_cast<std::size_t>(*(static_cast<uint8_t*>(ptr) - 1)) + 1;
void* original = static_cast<void*>(static_cast<uint8_t*>(ptr) - offset);
check_that_malloc_is_allowed();
check_that_free_is_allowed();
EIGEN_USING_STD(free)
free(original);
}
@@ -227,7 +242,7 @@ EIGEN_DEVICE_FUNC inline void aligned_free(void* ptr) {
#if (EIGEN_DEFAULT_ALIGN_BYTES == 0) || EIGEN_MALLOC_ALREADY_ALIGNED
if (ptr != nullptr) {
check_that_malloc_is_allowed();
check_that_free_is_allowed();
EIGEN_USING_STD(free)
free(ptr);
}
@@ -299,7 +314,7 @@ EIGEN_DEVICE_FUNC inline void conditional_aligned_free(void* ptr) {
template <>
EIGEN_DEVICE_FUNC inline void conditional_aligned_free<false>(void* ptr) {
if (ptr != nullptr) {
check_that_malloc_is_allowed();
check_that_free_is_allowed();
EIGEN_USING_STD(free)
free(ptr);
}