The documentation is being too helpful when it says that the initial value the system allocates for TLS is zero. The statement is true but not useful.
The reason is that applications can free TLS slots by calling TlsFree
, so when you allocate a slot, there is no guarantee that you are the first person ever to be given that slot. Therefore, you don't know whether the value is the initial 0 assigned by the system or some other junk value assigned by the previous owner of the slot.
Consider:
- Component A calls
TlsAlloc
and gets assigned slot 1. Slot 1 has never been used, so it contains its initial value of 0. - Component A calls
TlsSetValue(1, someValue)
. - Component A calls
TlsGetValue(1)
and it getssomeValue
back. - Component A is finished and calls
TlsFree(1)
. - Component B calls
TlsAlloc
and gets assigned slot 1. - Component B calls
TlsGetValue(1)
and getssomeValue
back because that is the garbage value left behind by component A.
Therefore, it is up the programmer to ensure that the thread calls TlsSetValue
before calling TlsGetValue
. Otherwise, your TlsGetValue
will read leftover garbage.
The misleading documentation is saying "The default value of leftover garbage is zero," but that's not helpful because you have no idea what happened to the slot between the time the system initialized it and it eventually got given to you.
Adrian's follow-up prompted me to study the situation again, and indeed the kernel zeroes out the slot when Component A calls TlsFree(1)
, so that when component B calls TlsGetValue(1)
it gets zero. This assumes that there is not a bug in Component A where it calls TlsSetValue(1)
after TlsFree(1)
.