This commit is contained in:
William Woodall 2015-12-10 17:06:18 -08:00
parent fb9f660443
commit bd3e4e8f58
25 changed files with 128 additions and 93 deletions

View file

@ -24,7 +24,8 @@ extern "C"
/// Encapsulation of an allocator. /// Encapsulation of an allocator.
/* To use malloc, free, and realloc use rcl_get_default_allocator */ /* To use malloc, free, and realloc use rcl_get_default_allocator */
typedef struct rcl_allocator_t { typedef struct rcl_allocator_t
{
/// Allocate memory, given a size and state structure. /// Allocate memory, given a size and state structure.
/* An error should be indicated by returning null. */ /* An error should be indicated by returning null. */
void * (*allocate)(size_t size, void * state); void * (*allocate)(size_t size, void * state);

View file

@ -26,12 +26,14 @@ extern "C"
struct rcl_guard_condition_impl_t; struct rcl_guard_condition_impl_t;
/// Handle for a rcl guard condition. /// Handle for a rcl guard condition.
typedef struct rcl_guard_condition_t { typedef struct rcl_guard_condition_t
{
struct rcl_guard_condition_impl_t * impl; struct rcl_guard_condition_impl_t * impl;
} rcl_guard_condition_t; } rcl_guard_condition_t;
/// Options available for a rcl guard condition. /// Options available for a rcl guard condition.
typedef struct rcl_guard_condition_options_t { typedef struct rcl_guard_condition_options_t
{
/// Custom allocator for the guard condition, used for incidental allocations. /// Custom allocator for the guard condition, used for incidental allocations.
/* For default behavior (malloc/free), use: rcl_get_default_allocator() */ /* For default behavior (malloc/free), use: rcl_get_default_allocator() */
rcl_allocator_t allocator; rcl_allocator_t allocator;

View file

@ -29,12 +29,14 @@ extern "C"
struct rcl_node_impl_t; struct rcl_node_impl_t;
/// Handle for a ROS node. /// Handle for a ROS node.
typedef struct rcl_node_t { typedef struct rcl_node_t
{
/// Private implementation pointer. /// Private implementation pointer.
struct rcl_node_impl_t * impl; struct rcl_node_impl_t * impl;
} rcl_node_t; } rcl_node_t;
typedef struct rcl_node_options_t { typedef struct rcl_node_options_t
{
// bool anonymous_name; // bool anonymous_name;
// rmw_qos_profile_t parameter_qos; // rmw_qos_profile_t parameter_qos;
/// If true, no parameter infrastructure will be setup. /// If true, no parameter infrastructure will be setup.

View file

@ -28,12 +28,14 @@ extern "C"
struct rcl_publisher_impl_t; struct rcl_publisher_impl_t;
/// Handle for a rcl publisher. /// Handle for a rcl publisher.
typedef struct rcl_publisher_t { typedef struct rcl_publisher_t
{
struct rcl_publisher_impl_t * impl; struct rcl_publisher_impl_t * impl;
} rcl_publisher_t; } rcl_publisher_t;
/// Options available for a rcl publisher. /// Options available for a rcl publisher.
typedef struct rcl_publisher_options_t { typedef struct rcl_publisher_options_t
{
/// Middleware quality of service settings for the publisher. /// Middleware quality of service settings for the publisher.
rmw_qos_profile_t qos; rmw_qos_profile_t qos;
/// Custom allocator for the publisher, used for incidental allocations. /// Custom allocator for the publisher, used for incidental allocations.

View file

@ -28,12 +28,14 @@ extern "C"
struct rcl_subscription_impl_t; struct rcl_subscription_impl_t;
/// Handle for a rcl subscription. /// Handle for a rcl subscription.
typedef struct rcl_subscription_t { typedef struct rcl_subscription_t
{
struct rcl_subscription_impl_t * impl; struct rcl_subscription_impl_t * impl;
} rcl_subscription_t; } rcl_subscription_t;
/// Options available for a rcl subscription. /// Options available for a rcl subscription.
typedef struct rcl_subscription_options_t { typedef struct rcl_subscription_options_t
{
/// Middleware quality of service settings for the subscription. /// Middleware quality of service settings for the subscription.
rmw_qos_profile_t qos; rmw_qos_profile_t qos;
/// If true, messages published from within the same node are ignored. /// If true, messages published from within the same node are ignored.

View file

@ -42,7 +42,8 @@ extern "C"
* The struct is capable of representing any time until the year 2554 with * The struct is capable of representing any time until the year 2554 with
* nanosecond precisions. * nanosecond precisions.
*/ */
typedef struct rcl_system_time_point_t { typedef struct rcl_system_time_point_t
{
uint64_t nanoseconds; uint64_t nanoseconds;
} rcl_system_time_point_t; } rcl_system_time_point_t;
@ -56,7 +57,8 @@ typedef struct rcl_system_time_point_t {
* *
* The struct represents time as nanoseconds in an unsigned 64-bit integer. * The struct represents time as nanoseconds in an unsigned 64-bit integer.
*/ */
typedef struct rcl_steady_time_point_t { typedef struct rcl_steady_time_point_t
{
uint64_t nanoseconds; uint64_t nanoseconds;
} rcl_steady_time_point_t; } rcl_steady_time_point_t;
@ -64,7 +66,8 @@ typedef struct rcl_steady_time_point_t {
/* The struct can represent any time within the range [~292 years, ~-292 years] /* The struct can represent any time within the range [~292 years, ~-292 years]
* with nanosecond precision. * with nanosecond precision.
*/ */
typedef struct rcl_duration_t { typedef struct rcl_duration_t
{
int64_t nanoseconds; int64_t nanoseconds;
} rcl_duration_t; } rcl_duration_t;

View file

@ -30,7 +30,8 @@ extern "C"
struct rcl_timer_impl_t; struct rcl_timer_impl_t;
/// Handle for a ROS timer. /// Handle for a ROS timer.
typedef struct rcl_timer_t { typedef struct rcl_timer_t
{
/// Private implementation pointer. /// Private implementation pointer.
struct rcl_timer_impl_t * impl; struct rcl_timer_impl_t * impl;
} rcl_timer_t; } rcl_timer_t;

View file

@ -31,7 +31,8 @@ extern "C"
struct rcl_wait_set_impl_t; struct rcl_wait_set_impl_t;
/// Container for subscription's, guard condition's, etc to be waited on. /// Container for subscription's, guard condition's, etc to be waited on.
typedef struct rcl_wait_set_t { typedef struct rcl_wait_set_t
{
/// Storage for subscription pointers. /// Storage for subscription pointers.
const rcl_subscription_t ** subscriptions; const rcl_subscription_t ** subscriptions;
size_t size_of_subscriptions; size_t size_of_subscriptions;

View file

@ -23,7 +23,8 @@ extern "C"
#include "rcl/rcl.h" #include "rcl/rcl.h"
#include "rmw/rmw.h" #include "rmw/rmw.h"
typedef struct rcl_guard_condition_impl_t { typedef struct rcl_guard_condition_impl_t
{
rmw_guard_condition_t * rmw_handle; rmw_guard_condition_t * rmw_handle;
rcl_guard_condition_options_t options; rcl_guard_condition_options_t options;
} rcl_guard_condition_impl_t; } rcl_guard_condition_impl_t;

View file

@ -28,7 +28,8 @@ extern "C"
#include "./common.h" #include "./common.h"
typedef struct rcl_node_impl_t { typedef struct rcl_node_impl_t
{
rcl_node_options_t options; rcl_node_options_t options;
rmw_node_t * rmw_node_handle; rmw_node_t * rmw_node_handle;
uint64_t rcl_instance_id; uint64_t rcl_instance_id;
@ -80,7 +81,7 @@ rcl_node_init(rcl_node_t * node, const char * name, const rcl_node_options_t * o
goto fail; goto fail;
} }
if (ros_domain_id) { if (ros_domain_id) {
unsigned long number = strtoul(ros_domain_id, NULL, 0); unsigned long number = strtoul(ros_domain_id, NULL, 0); // NOLINT(runtime/int)
if (number == ULONG_MAX) { if (number == ULONG_MAX) {
RCL_SET_ERROR_MSG("failed to interpret ROS_DOMAIN_ID as integral number"); RCL_SET_ERROR_MSG("failed to interpret ROS_DOMAIN_ID as integral number");
goto fail; goto fail;

View file

@ -24,7 +24,8 @@ extern "C"
#include "./common.h" #include "./common.h"
#include "rmw/rmw.h" #include "rmw/rmw.h"
typedef struct rcl_publisher_impl_t { typedef struct rcl_publisher_impl_t
{
rcl_publisher_options_t options; rcl_publisher_options_t options;
rmw_publisher_t * rmw_handle; rmw_publisher_t * rmw_handle;
} rcl_publisher_impl_t; } rcl_publisher_impl_t;

View file

@ -65,7 +65,7 @@ rcl_init(int argc, char ** argv, rcl_allocator_t allocator)
memset(__rcl_argv, 0, sizeof(char **) * argc); memset(__rcl_argv, 0, sizeof(char **) * argc);
for (size_t i = 0; i < argc; ++i) { for (size_t i = 0; i < argc; ++i) {
__rcl_argv[i] = (char *)__rcl_allocator.allocate(strlen(argv[i]), __rcl_allocator.state); __rcl_argv[i] = (char *)__rcl_allocator.allocate(strlen(argv[i]), __rcl_allocator.state);
strcpy(__rcl_argv[i], argv[i]); strcpy(__rcl_argv[i], argv[i]); // NOLINT(runtime/printf)
} }
atomic_store(&__rcl_instance_id, ++__rcl_next_unique_id); atomic_store(&__rcl_instance_id, ++__rcl_next_unique_id);
if (atomic_load(&__rcl_instance_id) == 0) { if (atomic_load(&__rcl_instance_id) == 0) {

View file

@ -22,7 +22,8 @@ extern "C"
#include "rmw/rmw.h" #include "rmw/rmw.h"
#include "./common.h" #include "./common.h"
typedef struct rcl_subscription_impl_t { typedef struct rcl_subscription_impl_t
{
rcl_subscription_options_t options; rcl_subscription_options_t options;
rmw_subscription_t * rmw_handle; rmw_subscription_t * rmw_handle;
} rcl_subscription_impl_t; } rcl_subscription_impl_t;

View file

@ -23,7 +23,8 @@ extern "C"
#include "./common.h" #include "./common.h"
typedef struct rcl_timer_impl_t { typedef struct rcl_timer_impl_t
{
// The user supplied callback. // The user supplied callback.
atomic_uintptr_t callback; atomic_uintptr_t callback;
// This is a duration in nanoseconds. // This is a duration in nanoseconds.

View file

@ -29,7 +29,8 @@ extern "C"
#include "rmw/rmw.h" #include "rmw/rmw.h"
#include "./common.h" #include "./common.h"
typedef struct rcl_wait_set_impl_t { typedef struct rcl_wait_set_impl_t
{
size_t subscription_index; size_t subscription_index;
rmw_subscriptions_t rmw_subscriptions; rmw_subscriptions_t rmw_subscriptions;
size_t guard_condition_index; size_t guard_condition_index;
@ -217,8 +218,7 @@ rcl_wait_set_get_allocator(const rcl_wait_set_t * wait_set, rcl_allocator_t * al
wait_set->Type ## s = NULL; \ wait_set->Type ## s = NULL; \
} \ } \
ExtraDealloc \ ExtraDealloc \
} \ } else { \
else { \
wait_set->size_of_ ## Type ## s = 0; \ wait_set->size_of_ ## Type ## s = 0; \
wait_set->Type ## s = (const rcl_ ## Type ## _t * *)allocator.reallocate( \ wait_set->Type ## s = (const rcl_ ## Type ## _t * *)allocator.reallocate( \
wait_set->Type ## s, sizeof(rcl_ ## Type ## _t *) * size, allocator.state); \ wait_set->Type ## s, sizeof(rcl_ ## Type ## _t *) * size, allocator.state); \
@ -336,7 +336,7 @@ rcl_wait_set_clear_timers(rcl_wait_set_t * wait_set)
rcl_ret_t rcl_ret_t
rcl_wait_set_resize_timers(rcl_wait_set_t * wait_set, size_t size) rcl_wait_set_resize_timers(rcl_wait_set_t * wait_set, size_t size)
{ {
SET_RESIZE(timer, ;, ;) SET_RESIZE(timer,;,;) // NOLINT
} }
rcl_ret_t rcl_ret_t
@ -397,8 +397,7 @@ rcl_wait(rcl_wait_set_t * wait_set, int64_t timeout)
&wait_set->impl->rmw_guard_conditions, &wait_set->impl->rmw_guard_conditions,
&dummy_services, &dummy_services,
&dummy_clients, &dummy_clients,
timeout_argument timeout_argument);
);
// Check for error. // Check for error.
if (ret != RMW_RET_OK) { if (ret != RMW_RET_OK) {
RCL_SET_ERROR_MSG(rmw_get_error_string_safe()); RCL_SET_ERROR_MSG(rmw_get_error_string_safe());

View file

@ -16,29 +16,32 @@
// https://dxr.mozilla.org/mozilla-central/rev/ // https://dxr.mozilla.org/mozilla-central/rev/
// cc9c6cd756cb744596ba039dcc5ad3065a7cc3ea/memory/build/replace_malloc.c // cc9c6cd756cb744596ba039dcc5ad3065a7cc3ea/memory/build/replace_malloc.c
#ifndef TEST__MEMORY_TOOLS_HPP_ #ifndef MEMORY_TOOLS_HPP_
#define TEST__MEMORY_TOOLS_HPP_ #define MEMORY_TOOLS_HPP_
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <stddef.h>
#include <functional> #include <functional>
#include <stddef.h>
typedef std::function<void ()> UnexpectedCallbackType; typedef std::function<void ()> UnexpectedCallbackType;
void start_memory_checking(); void start_memory_checking();
#define ASSERT_NO_MALLOC(statements) assert_no_malloc_begin(); statements; assert_no_malloc_end(); #define ASSERT_NO_MALLOC(statements) \
assert_no_malloc_begin(); statements; assert_no_malloc_end();
void assert_no_malloc_begin(); void assert_no_malloc_begin();
void assert_no_malloc_end(); void assert_no_malloc_end();
void set_on_unepexcted_malloc_callback(UnexpectedCallbackType callback); void set_on_unepexcted_malloc_callback(UnexpectedCallbackType callback);
#define ASSERT_NO_REALLOC(statements) assert_no_realloc_begin(); statements; assert_no_realloc_end(); #define ASSERT_NO_REALLOC(statements) \
assert_no_realloc_begin(); statements; assert_no_realloc_end();
void assert_no_realloc_begin(); void assert_no_realloc_begin();
void assert_no_realloc_end(); void assert_no_realloc_end();
void set_on_unepexcted_realloc_callback(UnexpectedCallbackType callback); void set_on_unepexcted_realloc_callback(UnexpectedCallbackType callback);
#define ASSERT_NO_FREE(statements) assert_no_free_begin(); statements; assert_no_free_end(); #define ASSERT_NO_FREE(statements) \
assert_no_free_begin(); statements; assert_no_free_end();
void assert_no_free_begin(); void assert_no_free_begin();
void assert_no_free_end(); void assert_no_free_end();
void set_on_unepexcted_free_callback(UnexpectedCallbackType callback); void set_on_unepexcted_free_callback(UnexpectedCallbackType callback);
@ -47,4 +50,4 @@ void stop_memory_checking();
void memory_checking_thread_init(); void memory_checking_thread_init();
#endif // TEST__MEMORY_TOOLS_HPP_ #endif // MEMORY_TOOLS_HPP_

View file

@ -39,7 +39,8 @@ void set_on_unepexcted_malloc_callback(UnexpectedCallbackType callback)
return; return;
} }
if (!unexpected_malloc_callback) { if (!unexpected_malloc_callback) {
unexpected_malloc_callback = (UnexpectedCallbackType *)malloc(sizeof(UnexpectedCallbackType)); unexpected_malloc_callback =
reinterpret_cast<UnexpectedCallbackType *>(malloc(sizeof(UnexpectedCallbackType)));
if (!unexpected_malloc_callback) { if (!unexpected_malloc_callback) {
throw std::bad_alloc(); throw std::bad_alloc();
} }
@ -51,7 +52,7 @@ void set_on_unepexcted_malloc_callback(UnexpectedCallbackType callback)
void * void *
custom_malloc(size_t size) custom_malloc(size_t size)
{ {
if (!enabled.load()) return malloc(size); if (!enabled.load()) {return malloc(size);}
auto foo = SCOPE_EXIT(enabled.store(true);); auto foo = SCOPE_EXIT(enabled.store(true););
enabled.store(false); enabled.store(false);
if (!malloc_expected) { if (!malloc_expected) {
@ -78,7 +79,8 @@ void set_on_unepexcted_realloc_callback(UnexpectedCallbackType callback)
return; return;
} }
if (!unexpected_realloc_callback) { if (!unexpected_realloc_callback) {
unexpected_realloc_callback = (UnexpectedCallbackType *)malloc(sizeof(UnexpectedCallbackType)); unexpected_realloc_callback =
reinterpret_cast<UnexpectedCallbackType *>(malloc(sizeof(UnexpectedCallbackType)));
if (!unexpected_realloc_callback) { if (!unexpected_realloc_callback) {
throw std::bad_alloc(); throw std::bad_alloc();
} }
@ -90,7 +92,7 @@ void set_on_unepexcted_realloc_callback(UnexpectedCallbackType callback)
void * void *
custom_realloc(void * memory_in, size_t size) custom_realloc(void * memory_in, size_t size)
{ {
if (!enabled.load()) return realloc(memory_in, size); if (!enabled.load()) {return realloc(memory_in, size);}
auto foo = SCOPE_EXIT(enabled.store(true);); auto foo = SCOPE_EXIT(enabled.store(true););
enabled.store(false); enabled.store(false);
if (!realloc_expected) { if (!realloc_expected) {
@ -118,7 +120,8 @@ void set_on_unepexcted_free_callback(UnexpectedCallbackType callback)
return; return;
} }
if (!unexpected_free_callback) { if (!unexpected_free_callback) {
unexpected_free_callback = (UnexpectedCallbackType *)malloc(sizeof(UnexpectedCallbackType)); unexpected_free_callback =
reinterpret_cast<UnexpectedCallbackType *>(malloc(sizeof(UnexpectedCallbackType)));
if (!unexpected_free_callback) { if (!unexpected_free_callback) {
throw std::bad_alloc(); throw std::bad_alloc();
} }
@ -130,7 +133,7 @@ void set_on_unepexcted_free_callback(UnexpectedCallbackType callback)
void void
custom_free(void * memory) custom_free(void * memory)
{ {
if (!enabled.load()) return free(memory); if (!enabled.load()) {return free(memory);}
auto foo = SCOPE_EXIT(enabled.store(true);); auto foo = SCOPE_EXIT(enabled.store(true););
enabled.store(false); enabled.store(false);
if (!free_expected) { if (!free_expected) {

View file

@ -20,7 +20,8 @@
// used an interposition table like the following: // used an interposition table like the following:
// //
typedef struct interpose_s { typedef struct interpose_s
{
void * new_func; void * new_func;
void * orig_func; void * orig_func;
} interpose_t; } interpose_t;
@ -28,8 +29,8 @@ typedef struct interpose_s {
#define OSX_INTERPOSE(newf, oldf) \ #define OSX_INTERPOSE(newf, oldf) \
__attribute__((used)) static const interpose_t \ __attribute__((used)) static const interpose_t \
macinterpose ## newf ## oldf __attribute__ ((section("__DATA, __interpose"))) = { \ macinterpose ## newf ## oldf __attribute__ ((section("__DATA, __interpose"))) = { \
(void *)newf, \ reinterpret_cast<void *>(newf), \
(void *)oldf, \ reinterpret_cast<void *>(oldf), \
} }
// End Interpose. // End Interpose.

View file

@ -18,7 +18,8 @@
#include "../memory_tools.hpp" #include "../memory_tools.hpp"
class TestAllocatorFixture : public ::testing::Test { class TestAllocatorFixture : public::testing::Test
{
public: public:
TestAllocatorFixture() TestAllocatorFixture()
{ {
@ -47,17 +48,22 @@ public:
/* Tests the default allocator. /* Tests the default allocator.
*/ */
TEST_F(TestAllocatorFixture, test_default_allocator_normal) TEST_F(TestAllocatorFixture, test_default_allocator_normal) {
{
ASSERT_NO_MALLOC( ASSERT_NO_MALLOC(
rcl_allocator_t allocator = rcl_get_default_allocator(); rcl_allocator_t allocator = rcl_get_default_allocator();
) )
size_t mallocs = 0; size_t mallocs = 0;
size_t reallocs = 0; size_t reallocs = 0;
size_t frees = 0; size_t frees = 0;
set_on_unepexcted_malloc_callback([&mallocs]() {mallocs++;}); set_on_unepexcted_malloc_callback([&mallocs]() {
set_on_unepexcted_realloc_callback([&reallocs]() {reallocs++;}); mallocs++;
set_on_unepexcted_free_callback([&frees]() {frees++;}); });
set_on_unepexcted_realloc_callback([&reallocs]() {
reallocs++;
});
set_on_unepexcted_free_callback([&frees]() {
frees++;
});
assert_no_malloc_begin(); assert_no_malloc_begin();
assert_no_realloc_begin(); assert_no_realloc_begin();
assert_no_free_begin(); assert_no_free_begin();

View file

@ -21,7 +21,8 @@
#include "../memory_tools.hpp" #include "../memory_tools.hpp"
class TestTimeFixture : public ::testing::Test { class TestTimeFixture : public::testing::Test
{
public: public:
void SetUp() void SetUp()
{ {
@ -45,8 +46,7 @@ public:
/* Tests the rcl_system_time_point_now() function. /* Tests the rcl_system_time_point_now() function.
*/ */
TEST_F(TestTimeFixture, test_rcl_system_time_point_now) TEST_F(TestTimeFixture, test_rcl_system_time_point_now) {
{
assert_no_realloc_begin(); assert_no_realloc_begin();
rcl_ret_t ret = RCL_RET_OK; rcl_ret_t ret = RCL_RET_OK;
// Check for invalid argument error condition (allowed to alloc). // Check for invalid argument error condition (allowed to alloc).
@ -78,8 +78,7 @@ TEST_F(TestTimeFixture, test_rcl_system_time_point_now)
/* Tests the rcl_steady_time_point_now() function. /* Tests the rcl_steady_time_point_now() function.
*/ */
TEST_F(TestTimeFixture, test_rcl_steady_time_point_now) TEST_F(TestTimeFixture, test_rcl_steady_time_point_now) {
{
assert_no_realloc_begin(); assert_no_realloc_begin();
rcl_ret_t ret = RCL_RET_OK; rcl_ret_t ret = RCL_RET_OK;
// Check for invalid argument error condition (allowed to alloc). // Check for invalid argument error condition (allowed to alloc).

View file

@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#ifndef TEST__SCOPE_EXIT_HPP_ #ifndef SCOPE_EXIT_HPP_
#define TEST__SCOPE_EXIT_HPP_ #define SCOPE_EXIT_HPP_
#include <functional> #include <functional>
@ -37,4 +37,4 @@ make_scope_exit(Callable callable)
#define SCOPE_EXIT(code) make_scope_exit([&]() {code; }) #define SCOPE_EXIT(code) make_scope_exit([&]() {code; })
#endif // TEST__SCOPE_EXIT_HPP_ #endif // SCOPE_EXIT_HPP_

View file

@ -18,16 +18,21 @@
/* Tests the allocatation checking tools. /* Tests the allocatation checking tools.
*/ */
TEST(TestMemoryTools, test_allocation_checking_tools) TEST(TestMemoryTools, test_allocation_checking_tools) {
{
size_t unexpected_mallocs = 0; size_t unexpected_mallocs = 0;
auto on_unexpected_malloc = [&unexpected_mallocs]() {unexpected_mallocs++;}; auto on_unexpected_malloc = ([&unexpected_mallocs]() {
unexpected_mallocs++;
});
set_on_unepexcted_malloc_callback(on_unexpected_malloc); set_on_unepexcted_malloc_callback(on_unexpected_malloc);
size_t unexpected_reallocs = 0; size_t unexpected_reallocs = 0;
auto on_unexpected_realloc = [&unexpected_reallocs]() {unexpected_reallocs++;}; auto on_unexpected_realloc = ([&unexpected_reallocs]() {
unexpected_reallocs++;
});
set_on_unepexcted_realloc_callback(on_unexpected_realloc); set_on_unepexcted_realloc_callback(on_unexpected_realloc);
size_t unexpected_frees = 0; size_t unexpected_frees = 0;
auto on_unexpected_free = [&unexpected_frees]() {unexpected_frees++;}; auto on_unexpected_free = ([&unexpected_frees]() {
unexpected_frees++;
});
set_on_unepexcted_free_callback(on_unexpected_free); set_on_unepexcted_free_callback(on_unexpected_free);
void * mem = nullptr; void * mem = nullptr;
// First try before enabling, should have no effect. // First try before enabling, should have no effect.