I am looking at how to track whether memory has been allocated or freed. The SCRIPT_STRING_ANALYSIS opaque point in usp10 can be freed in a number of places. It seems that Windows handles this by checking a list of allocated storage as the passed value of a SCRIPT_STRING_ANALYSIS could be invalid. An obvious problem is where SCRIPT_STRING_ANALYSIS pointer is passed or copied to another pointer. At best one pointer could be NULLed but not both. I have seen this behaviour. It seems that this would not be a unique problem in wine, is there a standard way to handle memory tracking so that if memory is freed, at a later time we can check to see if the pointer is still valid?
Jeff Latimer
Jeff L wrote:
I am looking at how to track whether memory has been allocated or freed. The SCRIPT_STRING_ANALYSIS opaque point in usp10 can be freed in a number of places. It seems that Windows handles this by checking a list of allocated storage as the passed value of a SCRIPT_STRING_ANALYSIS could be invalid. An obvious problem is where SCRIPT_STRING_ANALYSIS pointer is passed or copied to another pointer. At best one pointer could be NULLed but not both. I have seen this behaviour. It seems that this would not be a unique problem in wine, is there a standard way to handle memory tracking so that if memory is freed, at a later time we can check to see if the pointer is still valid?
It sounds like you could benefit from using the handle table functions in ntdll.
Robert Shearman wrote:
Jeff L wrote:
It seems that this would not be a unique problem in wine, is there a standard way to handle memory tracking so that if memory is freed, at a later time we can check to see if the pointer is still valid?
It sounds like you could benefit from using the handle table functions in ntdll.
Looks promising. There don't appear to be examples of how to use the functions. I assume that I declare memory to be of type RTL_HANDLE_TABLE and call RtlInitializeHandleTable to initialise it. Then there is a call to RtlpAllocateSomeHandles to get the space for the handles. After this RtlAllocateHandle gets a handle off the free list and RtlFreeHandle to release the handle.
How do you access the memory pointed to by the handle? I was thinking that I would need to stash the address I am managing into the handle. It looks like I can do that with the RTL_HANDLE pointer retuned by RtlAllocateHandle but from then on it does not look like I can get the address of the handle as RtlIsValidHandle etc do not return it.
If I run out of handles, how do I reallocate the table or add to it?
Are the functions thread safe if I anchor the handletable off a static variable in the dll? I am going to need a persistent table for the life of the dll. Hence it has the potential to be used by multiple threads.
Jeff Latimer
Jeff L wrote:
Robert Shearman wrote:
Jeff L wrote:
It seems that this would not be a unique problem in wine, is there a standard way to handle memory tracking so that if memory is freed, at a later time we can check to see if the pointer is still valid?
It sounds like you could benefit from using the handle table functions in ntdll.
Looks promising. There don't appear to be examples of how to use the functions. I assume that I declare memory to be of type RTL_HANDLE_TABLE and call RtlInitializeHandleTable to initialise it. Then there is a call to RtlpAllocateSomeHandles to get the space for the handles. After this RtlAllocateHandle gets a handle off the free list and RtlFreeHandle to release the handle.
How do you access the memory pointed to by the handle? I was thinking that I would need to stash the address I am managing into the handle. It looks like I can do that with the RTL_HANDLE pointer retuned by RtlAllocateHandle but from then on it does not look like I can get the address of the handle as RtlIsValidHandle etc do not return it.
Yes, it does. You can look at dlls/ntdll/tests/rtl.c to see how the functions can be used.
If I run out of handles, how do I reallocate the table or add to it?
You can't. It is intended to be a fixed size table.
Are the functions thread safe if I anchor the handletable off a static variable in the dll? I am going to need a persistent table for the life of the dll. Hence it has the potential to be used by multiple threads.
No. You need to protect the accessing of the handle table and handles with a critical section.
Robert Shearman wrote:
Jeff L wrote:
Robert Shearman wrote:
Yes, it does. You can look at dlls/ntdll/tests/rtl.c to see how the functions can be used.
Yep can see how that works now.
If I run out of handles, how do I reallocate the table or add to it?
You can't. It is intended to be a fixed size table.
In this case I assume that if I allocate a big table it would be ok to fail calls for more memory at some point due to the table being full.
Are the functions thread safe if I anchor the handletable off a static variable in the dll? I am going to need a persistent table for the life of the dll. Hence it has the potential to be used by multiple threads.
No. You need to protect the accessing of the handle table and handles with a critical section.
Another way looks like using TlsAlloc in dllmain to allocate TlsIndex to provide separate the storage anchors between threads and thus build in thread safe behaviour. Looks like an additional overhead in dll load and thread creation as opposed to the use of a lot of critical sections (see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/bas...). Is there any thought as to what the trade offs are in wine on the 2 approaches?
Jeff
Robert Shearman wrote:
Yes, it does. You can look at dlls/ntdll/tests/rtl.c to see how the functions can be used.
Looking at the tests as example it seems that you need to run InitFunctionPtrs() to set up pointers to the functions. I would want to do this in DllMain() as part of DLL_PROCESS_ATTACH: so the static pointers could be set up once however you can't issue a LoadLibraryA() inside DllMain(). The only other way to initialise the function pointers appears to be to use an Initialise routine that is called as part of any routine that may use the Table functions. I assume that it will be the latter option that I need to pursue. Is this the only way to access the Table functions?
Jeff Latimer
Jeff L wrote:
Robert Shearman wrote:
Yes, it does. You can look at dlls/ntdll/tests/rtl.c to see how the functions can be used.
Looking at the tests as example it seems that you need to run InitFunctionPtrs() to set up pointers to the functions. I would want to do this in DllMain() as part of DLL_PROCESS_ATTACH: so the static pointers could be set up once however you can't issue a LoadLibraryA() inside DllMain(). The only other way to initialise the function pointers appears to be to use an Initialise routine that is called as part of any routine that may use the Table functions. I assume that it will be the latter option that I need to pursue. Is this the only way to access the Table functions?
No, in Wine DLLs you can just link to ntdll, although it sounds as though handle tables aren't really the way to go for what you need.
Robert Shearman wrote:
although it sounds as though handle tables aren't really the way to go for what you need.
I have the this working now. Ta. Table may be ok for the function. Will submit a patch soon and see whether it is elegant enough as a way forward.
Jeff Latimer