Re: General memory management for embedded/extended perl with C threads
by beauregard (Monk) on Nov 14, 2004 at 20:37 UTC
|
It's most likely not a problem with using the "right" or "wrong" malloc function. It sounds more like you're freeing memory outside of where it's being allocated. For example, something gets allocated with the libc malloc() but gets freed with the perl PerlMem_free(). This is an issue for more than just perl extensions... anytime you use a library that might have been linked with a debugging memory allocator you can encounter this.
The rule of thumb is that you free memory in the same module you used to allocate it. That is, if you have a C library which exports a function like:
char* my_crappy_strdup( const char* str ) {
char* s = malloc(strlen(str)+1);
memcpy( s, str, strlen(str)+1 );
return s;
}
Then you also need to provide, in the same source file:
void my_crappy_free( char* str ) {
free(s);
}
And make sure that the caller of my_crappy_strdup() knows that they need to call my_crappy_free() on whatever data is created. Then it doesn't matter if that C library is using perl's memory manager, ElectricFence, libc, or whatever.
One of the interesting consequences of this, by the way, is that it's basically impossible to use libc's strdup() in perl extensions without some nasty #define magic because you'll never be able to get at the libc free() call...
c. | [reply] [d/l] [select] |
|
|
Thanks for the reply beauregard.
You are right, this was one of the major sources of crashes - however, I'm still left with that crash on a malloc in the C thread.
I've done a little more digging, and I'm wondering if it's because there is no Perl interpreter built in that C thread. If the standard Perl headers are used, then malloc gets redefined to use perl pointers associated with the thread - and since perl hasn't been set up: Boom! If this is the case, how do I get around that? I'm assuming it should be just a case of using the OS malloc/free for all memory management, then it shouldn't matter if a Perl interpreter has been built or not?
Thanks.
| [reply] |
Re: General memory management for embedded/extended perl with C threads
by osunderdog (Deacon) on Nov 15, 2004 at 02:38 UTC
|
You may already know this but there is discussion of memory allocation in perldoc perlguts.
It is suggested that you enable the version of malloc that is dis-
tributed with Perl. It keeps pools of various sizes of unallocated
memory in order to satisfy allocation requests more quickly. However,
on some platforms, it may cause spurious malloc or free errors.
I have found cases where perl's alloc doesn't play well in a threaded application. We had to revert to the OS alloc functions. Unfortunately if you use the OS alloc function, you will loose some very valuable debugging features. perldoc Devel::Peek.
Mr. Rock, please meet Mr. Hard Spot.
"Look, Shiny Things!" is not a better business strategy than compatibility and reuse.
OSUnderdog
| [reply] |
|
|
| [reply] |
|
|
To see what you're using now:
use Config qw|config_vars|;
print "Using Perl Malloc? ";
config_vars('usemymalloc');
print "\n";
I just ran through the perl configure and here is the salient question:
Do you wish to attempt to use the malloc that comes with perl5? [n]
"Look, Shiny Things!" is not a better business strategy than compatibility and reuse.
OSUnderdog
| [reply] [d/l] [select] |
Re: General memory management for embedded/extended perl with C threads
by BrowserUk (Patriarch) on Nov 15, 2004 at 14:03 UTC
|
With iThreads, under Win32, the memory for at least some of perl's internal datastructures is allocated from Thread Local Storage, and is so (at least notionally) only accessible from the thread in which it is created.
There is also (under 5.8.x at least) a C++ class wrapped around an OS provided LocalMemAlloc() API.
If either of these are the case with the version of Perl you are using, which is quite possible as iThreads evolved initially as a substitute for fork on Win32 in 5.6.1; and if you are allocating memory from the global heap in your C threads; and you are trying to share the two types of memory across both types of threads--this may explain (some) of your problems.
There are a lot of 'ifs' in that, and it may be a complete red herring, but like you I have attempted to track through the memory allocation macros used by Perl (5.8.5 in my case) and they are incredibly deeply nested and very hard to follow.
I think that your best source of advice would be the p5p list, and if your working on Win32 maybe the perl-win32 porters list also.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Time is a poor substitute for thought"--theorbtwo
"Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
| [reply] |
Re: General memory management for embedded/extended perl with C threads
by dave_the_m (Monsignor) on Nov 15, 2004 at 14:39 UTC
|
The offical interface to malloc() from XS is New, Newz,
Renew, Safefree. See the section "Memory Management"
in perlapi.pod
As an aside, note that you have to be very careful
when creating multiple threads inside perl. Most of perl's
data structures are private to each interpreter and are not designed
to be shared by multiple threads. So for example if you have
two threads accessing the same SV structure, madness will
ensue. Make sure that only the original thread that called the
XS code allocates/releases any further Perl data. If the other
threads only do private stuff unrelated to perl then that's
okay.
Dave. | [reply] |
|
|
Ok - I know what the problem is - I just don't know a proper solution:)
Just creating and initialising a Perl interpreter when the C thread starts solves all the problems, even though this C thread has no interaction with Perl at all . It seems when malloc and co are redefined, they use pointers that are associated with the current thread. In other words, when you use the Perl header files (XSUB.h and I suspect some of the others) there HAS to be an Perl interpreter initialised on all threads if you use malloc and it's friends.
Ideally, I don't want a Perl interpreter in each C thread:) There must be some way to build this module to use a global wide malloc?
| [reply] |