Skip to content

[C++] Use malloc/free instead of k_malloc/k_free in operator new/delete #20678

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

Merged
merged 2 commits into from
Nov 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions samples/cpp_synchronization/prj.conf
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
CONFIG_CPLUSPLUS=y
CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE=128
4 changes: 3 additions & 1 deletion subsys/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ zephyr_sources(
cpp_dtors.c
)

if (NOT CONFIG_LIB_CPLUSPLUS OR CONFIG_ZEPHYR_CPLUSPLUS)
if (NOT CONFIG_LIB_CPLUSPLUS AND
(NOT CONFIG_MINIMAL_LIBC OR
(CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE GREATER 0)))
zephyr_sources(
cpp_virtual.c
cpp_vtable.cpp
Expand Down
7 changes: 0 additions & 7 deletions subsys/cpp/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,6 @@ config RTTI
help
This option enables support of C++ RTTI.


config ZEPHYR_CPLUSPLUS
bool "Use Zephyr C++ Implementation"
help
Use Zephyr implementation for operator new, delete, pure virtual
functions and vtables.

endif # LIB_CPLUSPLUS

endif # ! MINIMAL_LIBC
Expand Down
93 changes: 7 additions & 86 deletions subsys/cpp/cpp_new.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,115 +4,36 @@
* SPDX-License-Identifier: Apache-2.0
*/

#if defined(CONFIG_LIB_CPLUSPLUS)
#include <new>
#endif // CONFIG_LIB_CPLUSPLUS
#include <kernel.h>
#include <stdlib.h>

void* operator new(size_t size)
{
#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
void* ptr = k_malloc(size);
#if defined(__cpp_exceptions) && defined(CONFIG_LIB_CPLUSPLUS)
if (!ptr)
throw std::bad_alloc();
#endif
return ptr;
#else
ARG_UNUSED(size);
return NULL;
#endif
return malloc(size);
}

void* operator new[](size_t size)
{
#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
void* ptr = k_malloc(size);
#if defined(__cpp_exceptions) && defined(CONFIG_LIB_CPLUSPLUS)
if (!ptr)
throw std::bad_alloc();
#endif
return ptr;
#else
ARG_UNUSED(size);
return NULL;
#endif
return malloc(size);
}

void operator delete(void* ptr) noexcept
{
#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
k_free(ptr);
#else
ARG_UNUSED(ptr);
#endif
free(ptr);
}

void operator delete[](void* ptr) noexcept
{
#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
k_free(ptr);
#else
ARG_UNUSED(ptr);
#endif
free(ptr);
}

#if defined(CONFIG_LIB_CPLUSPLUS)
void* operator new(size_t size, const std::nothrow_t&) noexcept
{
#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
return k_malloc(size);
#else
ARG_UNUSED(size);
return NULL;
#endif
}

void* operator new[](size_t size, const std::nothrow_t&) noexcept
{
#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
return k_malloc(size);
#else
ARG_UNUSED(size);
return NULL;
#endif
}

void operator delete(void* ptr, const std::nothrow_t&) noexcept
{
#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
k_free(ptr);
#else
ARG_UNUSED(ptr);
#endif
}

void operator delete[](void* ptr, const std::nothrow_t&) noexcept
{
#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
k_free(ptr);
#else
ARG_UNUSED(ptr);
#endif
}
#endif // CONFIG_LIB_CPLUSPLUS

#if (__cplusplus > 201103L)
void operator delete(void* ptr, size_t) noexcept
{
#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
k_free(ptr);
#else
ARG_UNUSED(ptr);
#endif
free(ptr);
}

void operator delete[](void* ptr, size_t) noexcept
{
#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
k_free(ptr);
#else
ARG_UNUSED(ptr);
#endif
free(ptr);
}
#endif // __cplusplus > 201103L
3 changes: 0 additions & 3 deletions subsys/cpp/cpp_vtable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
* @brief basic virtual tables required for classes to build
*
*/
#if !defined(CONFIG_LIB_CPLUSPLUS)

namespace __cxxabiv1 {
class __class_type_info {
virtual void dummy();
Expand All @@ -26,4 +24,3 @@ namespace __cxxabiv1 {
void __class_type_info::dummy() { } // causes the vtable to get created here
void __si_class_type_info::dummy() { } // causes the vtable to get created here
};
#endif // !defined(CONFIG_LIB_CPLUSPLUS)
1 change: 1 addition & 0 deletions tests/application_development/cpp/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ CONFIG_CPLUSPLUS=y
CONFIG_NET_BUF=y
CONFIG_ZTEST=y
CONFIG_ZTEST_STACKSIZE=2048
CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE=128
22 changes: 21 additions & 1 deletion tests/application_development/cpp/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@

#include <ztest.h>

class foo_class {
public:
foo_class(int foo) : foo(foo) {}
int get_foo() const { return foo;}
private:
int foo;
};

struct foo {
int v1;
};
Expand All @@ -49,7 +57,19 @@ static int test_init(struct device *dev)

SYS_INIT(test_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);


static void test_new_delete(void)
{
foo_class *test_foo = new foo_class(10);
zassert_equal(test_foo->get_foo(), 10, NULL);
delete test_foo;
}

void test_main(void)
{
/* Does nothing. This is a compile only test. */
ztest_test_suite(cpp_tests,
ztest_unit_test(test_new_delete)
);

ztest_run_test_suite(cpp_tests);
}
2 changes: 1 addition & 1 deletion tests/application_development/cpp/testcase.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
tests:
misc.app_dev.cpp:
arch_exclude: posix
build_only: true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this excluded?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a test case to cover new/delete and this onde can run in CI, before this change the test case did not contained any runnable test and was only build.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right but why did you exclude qemu_x86_coverage

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason qemu_x86_coverage hangs when running with c++.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need a bug filed on this, since this is an indicator that gathering code coverage will fail

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

created bug report #20729, looks like our own coverage code ends up in a endless loop

platform_exclude: qemu_x86_coverage
tags: cpp
1 change: 0 additions & 1 deletion tests/application_development/libcxx/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ CONFIG_NEWLIB_LIBC=y
CONFIG_CPLUSPLUS=y
CONFIG_LIB_CPLUSPLUS=y
CONFIG_STD_CPP17=y
CONFIG_HEAP_MEM_POOL_SIZE=1024
CONFIG_ZTEST=y
CONFIG_ZTEST_STACKSIZE=2048
6 changes: 0 additions & 6 deletions tests/application_development/libcxx/testcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@ tests:
platform_exclude: qemu_x86_coverage
min_flash: 54
tags: cpp
misc.app_dev.libcxx.zephyr_cpp:
arch_exclude: posix
platform_exclude: qemu_x86_coverage
tags: cpp
extra_configs:
- CONFIG_ZEPHYR_CPLUSPLUS=y
misc.app_dev.libcxx.exceptions:
arch_exclude: posix
platform_exclude: qemu_x86_coverage
Expand Down