diff --git a/dlls/msvcrt/thread.c b/dlls/msvcrt/thread.c
index e345bc9be25a8f030c11394a245068b3c6f5edef..08139084e48754943b84390d3f4dab8006d5a53c 100644
--- a/dlls/msvcrt/thread.c
+++ b/dlls/msvcrt/thread.c
@@ -5,6 +5,7 @@
  */
 #include "msvcrt.h"
 
+#include "msvcrt/malloc.h"
 #include "msvcrt/process.h"
 
 DEFAULT_DEBUG_CHANNEL(msvcrt);
@@ -21,9 +22,16 @@ typedef struct {
  */
 static DWORD CALLBACK _beginthread_trampoline(LPVOID arg)
 {
-  _beginthread_trampoline_t *trampoline = arg;
-  trampoline->start_address(trampoline->arglist);
-  return 0;
+    _beginthread_trampoline_t local_trampoline;
+
+    /* Maybe it's just being paranoid, but freeing arg right 
+     * away seems safer. 
+     */
+    memcpy(&local_trampoline,arg,sizeof(local_trampoline));
+    MSVCRT_free(arg);
+
+    local_trampoline.start_address(local_trampoline.arglist);
+    return 0;
 }
 
 /*********************************************************************
@@ -34,15 +42,20 @@ unsigned long _beginthread(
   unsigned int stack_size, /* [in] Stack size for new thread or 0 */
   void *arglist)           /* [in] Argument list to be passed to new thread or NULL */
 {
-  _beginthread_trampoline_t trampoline;
+  _beginthread_trampoline_t* trampoline;
 
   TRACE("(%p, %d, %p)\n", start_address, stack_size, arglist);
 
-  trampoline.start_address = start_address;
-  trampoline.arglist = arglist;
+  /* Allocate the trampoline here so that it is still valid when the thread 
+   * starts... typically after this function has returned.
+   * _beginthread_trampoline is responsible for freeing the trampoline
+   */
+  trampoline=MSVCRT_malloc(sizeof(*trampoline));
+  trampoline->start_address = start_address;
+  trampoline->arglist = arglist;
 
   /* FIXME */
-  return CreateThread(NULL, stack_size, _beginthread_trampoline, &trampoline, 0, NULL);
+  return CreateThread(NULL, stack_size, _beginthread_trampoline, trampoline, 0, NULL);
 }
 
 /*********************************************************************