diff --git a/CMakeLists.txt b/CMakeLists.txt index 47366c49..67bf860e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -384,6 +384,35 @@ if (MI_BUILD_TESTS) add_test(NAME test-${TEST_NAME} COMMAND mimalloc-test-${TEST_NAME}) endforeach() + + # Test for static initialization order of user vs mimalloc code, in various combinations + # of static and shared linkage. + # The "test" is that the executables don't crash. + set(STATIC_USER_SRC test/static-user.cpp test/static-user.h) + foreach(mimalloc_link mimalloc mimalloc-static) + set(libname_static static-user-static_${mimalloc_link}) + add_library(${libname_static} STATIC) + target_sources(${libname_static} PRIVATE ${STATIC_USER_SRC}) + target_compile_definitions(${libname_static} PRIVATE STATIC_USER_BUILD) + target_link_libraries(${libname_static} PUBLIC ${mimalloc_link}) + + set(libname_shared static-user-shared_${mimalloc_link}) + add_library(${libname_shared} SHARED) + target_sources(${libname_shared} PRIVATE ${STATIC_USER_SRC}) + target_compile_definitions(${libname_shared} PRIVATE STATIC_USER_BUILD) + target_compile_definitions(${libname_shared} PUBLIC STATIC_USER_SHARED) + target_link_libraries(${libname_shared} PUBLIC ${mimalloc_link}) + + foreach(static_user_type static shared) + set(static_user_lib_name static-user-${static_user_type}_${mimalloc_link}) + set(test_name test-${static_user_lib_name}) + add_executable(${test_name}) + target_sources(${test_name} PRIVATE test/test-static-user.c) + target_link_libraries(${test_name} PUBLIC ${static_user_lib_name}) + + add_test(NAME ${test_name} COMMAND ${test_name}) + endforeach() + endforeach() endif() # ----------------------------------------------------------------------------- diff --git a/test/static-user.cpp b/test/static-user.cpp new file mode 100644 index 00000000..2dff808a --- /dev/null +++ b/test/static-user.cpp @@ -0,0 +1,38 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2021 Frank Richter +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +#include "static-user.h" + +#include "mimalloc.h" + +struct HeapWrapper +{ + struct Container + { + mi_heap_t *heap; + }; + Container *container; + + HeapWrapper() + { + container = mi_malloc_tp(Container); + container->heap = mi_heap_new(); + } + ~HeapWrapper() + { + mi_heap_destroy(container->heap); + mi_free(container); + } +}; + +static HeapWrapper static_heap; + +void static_user_ref() +{ + auto *p = mi_heap_malloc(static_heap.container->heap, 123); + mi_free(p); +} diff --git a/test/static-user.h b/test/static-user.h new file mode 100644 index 00000000..4bf46670 --- /dev/null +++ b/test/static-user.h @@ -0,0 +1,42 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2021 Frank Richter +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +#ifndef STATIC_USER_H_ +#define STATIC_USER_H_ + +#if defined(_MSC_VER) || defined(__MINGW32__) +#define DLLEXPORT __declspec(dllexport) +#define DLLIMPORT __declspec(dllimport) +#elif defined(__GNUC__) +#define DLLEXPORT __attribute__((visibility("default"))) +#define DLLIMPORT +#else +#define DLLEXPORT +#define DLLIMPORT +#endif + +#if defined(STATIC_USER_SHARED) +#if defined(STATIC_USER_BUILD) +#define STATIC_USER_API DLLEXPORT +#else +#define STATIC_USER_API DLLIMPORT +#endif +#else +#define STATIC_USER_API +#endif + +#if defined(__cplusplus) +extern "C" { +#endif // defined(__cplusplus) + +STATIC_USER_API void static_user_ref(); + +#if defined(__cplusplus) +} // extern "C" +#endif // defined(__cplusplus) + +#endif // STATIC_USER_H_ diff --git a/test/test-static-user.c b/test/test-static-user.c new file mode 100644 index 00000000..0d5bc472 --- /dev/null +++ b/test/test-static-user.c @@ -0,0 +1,25 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2020, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" + +#include "static-user.h" +#include "testhelper.h" + +// --------------------------------------------------------------------------- +// Main testing +// --------------------------------------------------------------------------- +int main(void) { + mi_option_disable(mi_option_verbose); + + // The real test is whether the test executable crashes at exit + static_user_ref(); + + // --------------------------------------------------- + // Done + // ---------------------------------------------------[] + return print_test_summary(); +}