title: Does Windows's thread-local storage initialize values?
body: <p>I found a contradiction in MSDN regarding initial values for thread-local storage.  <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms686749%28v=vs.85%29.aspx" rel="noreferrer">This page</a> says:</p>
  
  <blockquote>
    <p>When the threads are created, the system allocates an array of LPVOID values for TLS, which are initialized to NULL.</p>
  </blockquote>
  
  <p>This leads me to believe that if I call TlsGetValue with a valid index from a thread that has never called TlsSetValue for the same index, then I should get a null pointer.</p>
  
  <p><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms686812%28v=vs.85%29.aspx" rel="noreferrer">This page</a>, however, says:</p>
  
  <blockquote>
    <p>It is up to the programmer to ensure ... that the thread calls TlsSetValue before calling TlsGetValue.</p>
  </blockquote>
  
  <p>This suggests that you cannot rely on the value returned from TlsGetValue unless you're sure it's been explicitly initialized with TlsSetValue.</p>
  
  <p>Yet the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms686812%28v=vs.85%29.aspx" rel="noreferrer">second page</a> simultaneously reinforces the initialized-to-null behavior by also saying:</p>
  
  <blockquote>
    <p>The data stored in a TLS slot can have a value of 0 because it still has its initial value or because the thread called the TlsSetValue function with 0.</p>
  </blockquote>
  
  <p>So I've got two statements saying that the data is initialized to null (or 0), and one saying that I must initialize it explicitly before reading the value.  Experimentally, the values do seem to be initialized to null pointers automatically, but I have no way of knowing if I'm just getting lucky and whether this will always be the case.</p>
  
  <p>I'm trying to avoid using a DLL just to allocate on DLL_THREAD_ATTACH.  I'd like to do lazy allocation along the lines of:</p>
  
  <pre><code>LPVOID pMyData = ::TlsGetValue(g_index);
  if (pMyData == nullptr) {
    pMyData = /* some allocation and initialization*/;
    // bail out if allocation or initialization failed
    ::TlsSetValue(g_index, pMyData);
  }
  DoSomethingWith(pMyData);
  </code></pre>
  
  <p>Is this a reliable and safe pattern?  Or do I have to explicitly initialize the slot in each thread before I ever try to read it?</p>
  
  <p><strong>UPDATE:</strong> The documentation also says that <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms686801%28v=vs.85%29.aspx" rel="noreferrer">TlsAlloc zeros out the slots for the allocated index</a>.  So whether or not a slot has previously been used by another part of the program seems irrelevant.</p>