I was doing something similar a short time ago. ActiveState Perl is built using a compiler that uses the run-time library that's used by the Windows internal stuff and many supplied apps, so that's easier. ActiveState Perl is built using a version of the compiler (from "PlatformSDK for Windows Server 2003 R2") that doesn't require the "Manifest" be inserted, and behaves normally if that DLL is just plain found, so that is easier.
The static lib is only available on 32-bit platforms, BTW.
The crash occurs because of memory heaps. Windows was designed to avoid this problem by having a per-process heap that all code can discover. The compiler RTL then circumvents this and creates a new heap instance. Had they used GetProcessHeap instead of CreateHeap (or whatever they are called), it would not have been an issue.
If code allocates memory from one heap and frees it on another, things break.
The solution would be for the main perl interpreter dll to export a malloc/free pair of functions that are to be used by all XS code. Maybe it does and is under appreciated. Maybe that feature is missing? I don't know.
—John
Updated. | [reply] |
ActiveState Perl is built using a compiler that uses the run-time library that's used by the Windows internal stuff and many supplied apps, so that's easier
Both ActiveState Perl and Strawberry Perl use the same C runtime. Wrt to cfreeman's specific issues, neither has any advantage over the other.
cfreeman have you considered using the MinGW compiler (that ships with Strawberry Perl, and is also freely available elsewhere) to build the dll's - instead of using the incompatible VC9 ? That would be the best solution, imo - there would then be no problem using those dll's with either ActivePerl or Strawberry Perl.
Cheers, Rob
| [reply] |
| [reply] |
See perlclib, XS code is supposed to use New/Safefree
| [reply] |
As anonymonk points out, XS code is meant to use New*() and Safefree(). In part, to avoid the predictable problems with multiple runtimes trying to manage heap memory. However, I find these PerlAPI functions inconvenient to use because of their non-standard calling syntax (a problem rife throughout the PerlAPI).
It means that you cannot initialise pointers in-line with their declarations. So, like many others, I've wrapped those APis in more convenient and intuative wrappers
void *Calloc( int n, int size ) {
void *p;
Newxz( p, n * size, char );
return p;
}
void Free( void *p ) {
Safefree( p );
}
Note the uppercase first chars. Done to avoid conflicts with the dozens of other definitions and re-definitions of calloc() and free() (along with malloc() et al.) spread throughout the Perl sources.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
Thanks for all the input - it is really appreciated. Anon - that's a really good tip about the new and safefree...I didn't know that. Sadly, it's actually a file pointer that's being passed. I tried it before with the perio functions, but of course the formats are different and changing it back over to a FILE * brings back the runtime conflict again.
I also tried compiling with minGW, but it seems compiler wrangling is not my forte. The libraries have to compile with VS (the perl is just a quick-start helper type thing), and I couldn't seem to get them to work correctly. To be honest, I didn't give this too much of a go because I did read that mingw compiles with msvcrt by default and I was worried I would spend a long time on it only to find that it's like Makemaker itself - theoretically possible to compile with another runtime, but only if you can work the voodoo properly.
Anyway, not the ideal solution, but what I ended up doing was basically working around the problem. Most of our source code for this is supplied in another package and it's required in order to install this one (libraries and code in the same group, perl XS in another). The code actually compiles from a few libraries, and only one does not have the source code supplied. I basically just went into the code, severed the file pointer connection between the source and non-source libraries, grabbed the source directory location from the registry using Win32API::Registry and compiled the source into the XS using the object attribute in the Makefile.PL as
OBJECT => '$(BASEEXT)$(OBJ_EXT) ".$extrafile."$(OBJ_EXT)'
and re-wrote the c_o functions to compile from the source directory.
Granted, it's not ideal, but really nothing about this whole thing is ideal. I can't imagine what you would do if you weren't able to re-compile the libraries at all. I think you'd be pretty screwed. I know microsoft calls both the manifest requirement and the random heap corruption a "feature" or that it "functions as designed", but to me this seems like a design flaw. Maybe I'm wrong - maybe the design is great and this is just a minuscule side effect that happened to hit me, but I can see lots of possible scenarios where this could bite you pretty badly. A lot of these problems could be so easily fixed too, if the manifest requirement was dropped (not even really sure why they are required anyway - the don't say much and they are easy to fake), and the DLL was shipped by default with windows.
Anyways, thanks everyone again - it was much appreciated. Hopefully the info about the new and safefree will help others who stumble onto this thread. I know I'll be keeping it in mind. | [reply] |