kopia lustrzana https://github.com/espressif/esp-idf
esp32: Adds C++ exceptions emergency pool size menuconfig option
rodzic
b83792f504
commit
7df96718a2
14
Kconfig
14
Kconfig
|
@ -93,7 +93,7 @@ config OPTIMIZATION_ASSERTIONS_DISABLED
|
|||
|
||||
endchoice # assertions
|
||||
|
||||
config CXX_EXCEPTIONS
|
||||
menuconfig CXX_EXCEPTIONS
|
||||
bool "Enable C++ exceptions"
|
||||
default n
|
||||
help
|
||||
|
@ -102,8 +102,16 @@ config CXX_EXCEPTIONS
|
|||
Disabling this option disables C++ exception support in all compiled files, and any libstdc++ code which throws
|
||||
an exception will abort instead.
|
||||
|
||||
Enabling this option currently adds an additional 20KB of heap overhead, and 4KB of additional heap is allocated
|
||||
the first time an exception is thrown in user code.
|
||||
Enabling this option currently adds an additional ~500 bytes of heap overhead
|
||||
when an exception is thrown in user code for the first time.
|
||||
|
||||
config CXX_EXCEPTIONS_EMG_POOL_SIZE
|
||||
int "Emergency Pool Size"
|
||||
default 0
|
||||
depends on CXX_EXCEPTIONS
|
||||
help
|
||||
Size (in bytes) of the emergency memory pool for C++ exceptions. This pool will be used to allocate
|
||||
memory for thrown exceptions when there is not enough memory on the heap.
|
||||
|
||||
endmenu # Compiler Options
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ class Base
|
|||
{
|
||||
public:
|
||||
virtual ~Base() {}
|
||||
virtual void foo() = 0;
|
||||
virtual void foo() = 0;
|
||||
};
|
||||
|
||||
class Derived : public Base
|
||||
|
@ -192,8 +192,13 @@ TEST_CASE("before scheduler has started, static initializers work correctly", "[
|
|||
|
||||
TEST_CASE("c++ exceptions work", "[cxx]")
|
||||
{
|
||||
/* Note: This test currently trips the memory leak threshold
|
||||
as libunwind allocates ~4KB of data on first exception. */
|
||||
/* Note: When first exception (in system) is thrown this test produces memory leaks report (~500 bytes):
|
||||
- 392 bytes (can vary) as libunwind allocates memory to keep stack frames info to handle exceptions.
|
||||
This info is kept until global destructors are called by __do_global_dtors_aux()
|
||||
- 8 bytes are allocated by __cxa_get_globals() to keep __cxa_eh_globals
|
||||
- 16 bytes are allocated by pthread_setspecific() which is called by __cxa_get_globals() to init TLS var for __cxa_eh_globals
|
||||
- 88 bytes are allocated by pthread_setspecific() to init internal lock
|
||||
*/
|
||||
int thrown_value;
|
||||
try
|
||||
{
|
||||
|
@ -207,6 +212,60 @@ TEST_CASE("c++ exceptions work", "[cxx]")
|
|||
printf("OK?\n");
|
||||
}
|
||||
|
||||
TEST_CASE("c++ exceptions emergency pool", "[cxx] [ignore]")
|
||||
{
|
||||
/* Note: When first exception (in system) is thrown this test produces memory leaks report (~500 bytes):
|
||||
- 392 bytes (can vary) as libunwind allocates memory to keep stack frames info to handle exceptions.
|
||||
This info is kept until global destructors are called by __do_global_dtors_aux()
|
||||
- 8 bytes are allocated by __cxa_get_globals() to keep __cxa_eh_globals
|
||||
- 16 bytes are allocated by pthread_setspecific() which is called by __cxa_get_globals() to init TLS var for __cxa_eh_globals
|
||||
- 88 bytes are allocated by pthread_setspecific() to init internal lock
|
||||
*/
|
||||
void **p, **pprev = NULL;
|
||||
int thrown_value = 0;
|
||||
// throw first exception to ensure that all initial allocations are made
|
||||
try
|
||||
{
|
||||
throw 33;
|
||||
}
|
||||
catch (int e)
|
||||
{
|
||||
thrown_value = e;
|
||||
}
|
||||
TEST_ASSERT_EQUAL(33, thrown_value);
|
||||
// consume all dynamic memory
|
||||
while ((p = (void **)malloc(sizeof(void *)))) {
|
||||
if (pprev) {
|
||||
*p = pprev;
|
||||
} else {
|
||||
*p = NULL;
|
||||
}
|
||||
pprev = p;
|
||||
}
|
||||
try
|
||||
{
|
||||
throw 20;
|
||||
}
|
||||
catch (int e)
|
||||
{
|
||||
thrown_value = e;
|
||||
printf("Got exception %d\n", thrown_value);
|
||||
}
|
||||
#if CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE > 0
|
||||
// free all memory
|
||||
while (pprev) {
|
||||
p = (void **)(*pprev);
|
||||
free(pprev);
|
||||
pprev = p;
|
||||
}
|
||||
TEST_ASSERT_EQUAL(20, thrown_value);
|
||||
#else
|
||||
// if emergency pool is disabled we should never get here,
|
||||
// expect abort() due to lack of memory for new exception
|
||||
TEST_ASSERT_TRUE(0 == 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* These test cases pull a lot of code from libstdc++ and are disabled for now
|
||||
|
|
|
@ -397,6 +397,13 @@ void start_cpu1_default(void)
|
|||
}
|
||||
#endif //!CONFIG_FREERTOS_UNICORE
|
||||
|
||||
#ifdef CONFIG_CXX_EXCEPTIONS
|
||||
size_t __cxx_eh_arena_size_get()
|
||||
{
|
||||
return CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void do_global_ctors(void)
|
||||
{
|
||||
#ifdef CONFIG_CXX_EXCEPTIONS
|
||||
|
|
Ładowanie…
Reference in New Issue