01-12-2009 11:20 AM
Hello,
In continuation with my last post, I've got another problem, that might be the same, or it might be different.
I have 2 DLLs, a driver (driver.dll) and a support package (support.dll).
If support.dll has the function MyDLLAllocFunction() and it is simply:
void *MyDLLAllocFunction(void) {
return malloc(100);
}
And then in driver.dll I do
void *x;
x = MyDLLAllocFunction();
free(x);
I get an error at "free(x)" saying that it wasn't malloc'd or calloc'd, but it was, however in another DLL. How would I get all the library modules to share the same heap?
I'm using WinXP and CVI 9.0.
I observe this issue with DLLs (support.dll) that wasn't compiled with CVI, but where the driver.dll was, e.g. when I'm trying to use the library PCRE.dll compiled with MINGW32 (under Cygwin) and I need to do a free().
Thanks,
Jason.
Solved! Go to Solution.
01-12-2009 11:40 AM
01-12-2009 04:00 PM
Hello Jason,
The problem that you're having is that you are trying to mix and match the CVI ANSI C library with the ANSI C library of another compiler, and these cannot be combined in this way. For example, you cannot free a pointer in CVI that you allocated using a different compiler.
When you compile a program in CVI you are using the CVI version of the ANSI C library. But when you compile it with MSVC, for example, you are using the ANSI C implementation from the VC runtime instead. Even though the two libraries have the same interface, you cannot use them interchangeably to access the same data.
If you really need to free a pointer in one dll that you allocated in a different dll, and you can't compile both dlls with the same compiler, then you should pass a function pointer for the free() function from one dll to the other, so that the dll that needs to free the pointer can free it by calling the function pointer, instead of calling free() directly. The same applies to your fopen/fgetc situation.
An even better (cleaner) way to handle this is to export from your support dll both an allocation function and a dispose function which your driver dll can then call whenever it's done using the data.
Hope this helps,
Luis
01-13-2009 02:01 AM
Hi,
Any ideas why I can't free() a pointer from a DLL that was compiled with CVI?
mysupportlib.dll: (compiled with CVI)
void *func(void) { return malloc(100) };
mydriver.dll: (compiled with CVI)
void main(void) {
void *x;
x = func();
free(x); // Error here, unless malloc() is also in this function and we remove call to "func()"
}
It still looks like CVI is having a heap or separating heaps between DLLs, even though that's what TLS is supposed to be for. I really want to avoid having static libs for everything.
Thanks,
Jason.
01-13-2009 08:17 AM
As LuisG wrote:
An even better (cleaner) way to handle this is to export from your support dll both an allocation function and a dispose function which your driver dll can then call whenever it's done using the data.
An application and a DLL loaded by that application - even if they are both CVI code - will maintain different instances of their run-time support library so they will have separate heaps for memory allocation.
If you really don't want to export a memory de-allocation function from your DLL - which would be unusual as this is by far the most common way of handling these circumstances - I suppose you could use the Windows SDK LocalAlloc()/LocalReAlloc() and LocalDiscard() functions instead of malloc()/realloc() and free(); these use the Windows heap which should be the same across application and DLL.
01-13-2009 11:08 AM - edited 01-13-2009 11:10 AM
Actually, if both dlls are compiled by CVI, this should work. I just tested it using one of the CVI examples (I modified samples\dll\basic\cvidl.cws), and I didn't get an error when I freed the pointer.
If you have a test program that reproduces this error, would you mind attaching it here so that we could investigate?
Having said that, Martin's point is still valid: from a design standpoint, it's definitely preferable to export a de-allocation function.
Thanks,
Luis
01-13-2009 11:12 AM
01-14-2009 03:49 AM
I'll give it a shot with the same run time (one was Full, the other was Instrument).
As for being unusual, the Unix world does this often enough. The first example I gave is the getline() function from GNU that will automatically malloc() or realloc() as required, leaving the calling application to free() the memory.
My drivers that I write as DLLs naturally enough do have their own deallocators as they're used by various other languages.
07-05-2010 07:08 PM - edited 07-05-2010 07:10 PM
I have another experience in this same area.
I have a DLL that I made using CVI and I use Thread Local Storgae (TLS).
Part of the DLL_THREAD_ATTACH "reason" parameter when calling DllMain was doing a calloc to create the actual thread storage area, the pointer to which is managed as part of the TLS mechanism, which also requires a specialized alloc TlsAlloc() and free TlsFree(). You use TlsAlloc() to get an "index" for TLS, and you then separately alloc a memory block somewhere and put the pointer to it in the index that Win32 provided by the TlsAlloc() call.
On a thread detach, I would free this allocated memory with a simple free(memorypointer) call.
However, CVI would claim a memory leak despite the free() call for both the TLSAlloc and the calloc memory blocks.
I changed the calloc calls to LocalAlloc and the frees to LocalFree and now CVI no longer claims there's a memory leak after program termination for either the index or the actual TLS memory block.
So I wonder what's really happening here - the calloc and free calls returned without error.
I saw that MSDN example for TLS used LocalAlloc and LocalFree so when in Rome ...
Menchar