diff --git a/cpu/native/startup.c b/cpu/native/startup.c
index 2be966573bae8d22b8f30ec2fdf12d16f0b3a604..7a361fbd7c02e1bb9ef1f7d2ab341d55305f1a82 100644
--- a/cpu/native/startup.c
+++ b/cpu/native/startup.c
@@ -43,6 +43,9 @@
 #include "native_internal.h"
 #include "tty_uart.h"
 
+#define ENABLE_DEBUG (0)
+#include "debug.h"
+
 typedef enum {
     _STDIOTYPE_STDIO = 0,   /**< leave intact */
     _STDIOTYPE_NULL,        /**< redirect to "/dev/null" */
@@ -250,7 +253,22 @@ void usage_exit(int status)
     real_exit(status);
 }
 
-__attribute__((constructor)) static void startup(int argc, char **argv)
+/** @brief Initialization function pointer type */
+typedef void (*init_func_t)(int argc, char **argv, char **envp);
+#ifdef __APPLE__
+/* Taken from the sources of Apple's dyld launcher
+ * https://github.com/opensource-apple/dyld/blob/3f928f32597888c5eac6003b9199d972d49857b5/src/dyldInitialization.cpp#L85-L104
+ */
+/* Find the extents of the __DATA __mod_init_func section */
+extern init_func_t __init_array_start __asm("section$start$__DATA$__mod_init_func");
+extern init_func_t __init_array_end   __asm("section$end$__DATA$__mod_init_func");
+#else
+/* Linker script provides pointers to the beginning and end of the init array */
+extern init_func_t __init_array_start;
+extern init_func_t __init_array_end;
+#endif
+
+__attribute__((constructor)) static void startup(int argc, char **argv, char **envp)
 {
     _native_init_syscalls();
 
@@ -341,6 +359,39 @@ __attribute__((constructor)) static void startup(int argc, char **argv)
     _native_null_out_file = _native_log_output(stdouttype, STDOUT_FILENO);
     _native_input(stdintype);
 
+    /* startup is a constructor which is being called from the init_array during
+     * C runtime initialization, this is normally used for code which must run
+     * before launching main(), such as C++ global object constructors etc.
+     * However, this function (startup) misbehaves a bit when we call
+     * kernel_init below, which does not return until there is an abort or a
+     * power off command.
+     * We need all C++ global constructors and other initializers to run before
+     * we enter the normal application code, which may depend on global objects
+     * having been initalized properly. Therefore, we iterate through the
+     * remainder of the init_array and call any constructors which have been
+     * placed after startup in the initialization order.
+     */
+    init_func_t *init_array_ptr = &__init_array_start;
+    DEBUG("__init_array_start: %p\n", (void *)init_array_ptr);
+    while (init_array_ptr != &__init_array_end) {
+        /* Skip everything which has already been run */
+        if ((*init_array_ptr) == startup) {
+            /* Found ourselves, move on to calling the rest of the constructors */
+            DEBUG("%18p - myself\n", (void *)init_array_ptr);
+            ++init_array_ptr;
+            break;
+        }
+        DEBUG("%18p - skip\n", (void *)init_array_ptr);
+        ++init_array_ptr;
+    }
+    while (init_array_ptr != &__init_array_end) {
+        /* call all remaining constructors */
+        DEBUG("%18p - call\n", (void *)init_array_ptr);
+        (*init_array_ptr)(argc, argv, envp);
+        ++init_array_ptr;
+    }
+    DEBUG("done, __init_array_end: %p\n", (void *)init_array_ptr);
+
     native_cpu_init();
     native_interrupt_init();
 #ifdef MODULE_NETDEV_TAP