January 28th, 2026
mind blown1 reaction

Why did I lose the data even though I called Safe­Array­Add­Ref?

A customer had a method that received a SAFEARRAY, and they called Safe­Array­Add­Ref to add a reference to it so that they could continue using the array after the method returned, but they found that if they tried to use the array later, the safearray->pData was NULL, and if they called Safe­Array­Add­Ref again, it also gave them a null data pointer. They wanted to know if this was expected behavior. “Does COM invalidate a SAFEARRAY when a method returns, ignoring the reference count?”

Earlier, we looked at the difference between Safe­Array­Access­Data and Safe­Array­Add­Ref, and that will be the key to untangling this riddle.

Scripting SAFEARRAYs are not reference-counted objects. When somebody says to destroy them, they are destroyed.

The Safe­Array­Add­Ref function lets you extend the memory lifetime of the array descriptor and the array data, but the useful lifetime ends when the array is destroyed. The purpose of the Safe­Array­Add­Ref function is to prevent you from operating on freed memory if somebody destroys the array out from under you.

In this case, what happens is that the caller provides a SAFEARRAY, and you call Safe­Array­Add­Ref to extend its memory lifetime. When you return, the caller decides that it was a temporary array, so it calls Safe­Array­Destroy. This renders the array contents useless, but since you added a reference (to the descriptor and the data), the memory for them is not freed, even though they don’t contain anything useful any more.

After the array has been destroyed, your calls to Safe­Array­Add­Ref continue to extend the lifetime of the array descriptor and the data in it, but the descriptor had already been emptied out when the array was destroyed, so there is no data in the array any more. You are extending the lifetime of no data, which is why Safe­Array­Add­Ref produces a null pointer as the data pointer.

To access the original memory, you need to do it through the pointer returned from the original call to Safe­Array­Add­Ref.

But even that won’t help you, because the memory for the array data is zeroed out when the array is destroyed. You have a pointer to a bunch of zeroes.

Next time, we’ll look at ways of solving the customer’s problem, now that we understand why their approach didn’t work.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

0 comments