[pcre-dev] Mingw Memory mismatch problem

Startseite
Nachricht löschen
Autor: Bob Rossi
Datum:  
To: pcre-dev
CC: Brian Dessent
Betreff: [pcre-dev] Mingw Memory mismatch problem
Hi everyone,

I was able to test Brian's patch. He definately solved the problem.

Thanks Brian! I'm counting how many times I owe you, about to switch to
the second hand!

So, we need to decide if we want to release with his changes, or if
we want to solve it by actually using the __declspec's properly. I hope
the problem is clear from his email. I can do more testing or look at
the problem deeper if it's decided the "make all symbols public"
approach is no good.

Thanks,
Bob Rossi

----- Forwarded message from Brian Dessent <brian@???> -----

Date: Tue, 03 Apr 2007 11:39:52 -0700
From: Brian Dessent <brian@???>
To: MinGW Users List <mingw-users@???>
Subject: Re: [Mingw-users] pcre

Bob Rossi wrote:

> So, if I do,
>
> $ cd ..
> $ mkdir build-shared
> $ cd build-shared
> $ ../pcre-7.1-RC3/configure --prefix=$PWD/../prefix-shared
> --enable-shared --disable-static
> $ make
> $ make install
>
> all goes well. That builds the dll and a program pcretest.exe which
> links against the dll. If I run the test like this, (from a dos shell)
> $ .\pcretest.exe
> PCRE version 7.1-RC3 2007-03-26
>
>     re> /(a)b!/I
>   Size disagreement: pcre_fullinfo=61 call to malloc for 0
>   Capturing subpattern count = 1
>   No options
>   First char = 'a'
>   Need char = '!'

>
> There, you can see that the call to malloc failed. Is there some reason
> that the build would work but the runtime behavior wouldn't? BTW, if I
> build a static build only, the compile and runtime work fine.


malloc is not failing, it only looks that way.

libpcre provides function pointers (pcre_malloc, pcre_free, ...) that
the client can use to override the default allocation functions.
pcretest uses this feature to install its own new_malloc and friends.
However, on MinGW this feature is broken and libpcre ends up always
calling the system malloc/free. This means that pcretest's new_malloc
is never called, and consequently the global variable that it sets
(gotten_store) that is used to keep track of memory allocations is never
set. Since it's a static variable it gets initialized to 0, and all the
errors result from there. malloc is still called, and returns a valid
chunk of memory, so everything should work fine, it's just that the
ability to override malloc doesn't work.

Why is this broken? I'm not exactly sure. I think it has to do with
the fact that pcre_global.c looks like this after preprocessing:

/* from pcre.h via pcre_internal.h */
__declspec(dllexport) void *(*pcre_malloc)(size_t);

...

void *(*pcre_malloc)(size_t) = malloc;

Or maybe it's that internal modules of libpcre that access these
function pointers (e.g. pcre_exec.c:939) get them declared
__declspec(dllexport) because that is all that pcre.h knows how to do.
I think there really needs to be three use cases differentiated:

pcre_global.c: dllexport (and without the double declaration in pcre.h)
other libpcre internal modules: extern
client code that includes pcre.h: dllimport

Does that make sense?

In order to do this, I think you'd have to revisit the design of the
PCRE_DATA_SCOPE variable, perhaps make a new one that applies only to
these function pointers.

But in any case, there is a much easier solution -- do what Cygwin
does. In pcre.h, all of the __declspec stuff is conditionalized on
_WIN32. Cygwin does not define _WIN32, so there are no declspecs used,
just the standard C "extern". This means that auto-export can work to
export all the symbols (remember that if no __declspec(dllexport) is
seen anywhere, then auto-export is enabled without having to pass any
linker flags.) And automatic data imports take care of resolving the
function pointers on the client side:

Info: resolving _pcre_malloc by linking to __imp__pcre_malloc
(auto-import)
Info: resolving _pcre_free by linking to __imp__pcre_free (auto-import)
Info: resolving _pcre_stack_malloc by linking to
__imp__pcre_stack_malloc (auto-import)
Info: resolving _pcre_stack_free by linking to __imp__pcre_stack_free
(auto-import)
Info: resolving _pcre_callout by linking to __imp__pcre_callout
(auto-import)

So ironically, by removing all traces of __declspec, everything just
works. Of course, this has two problems: A) all symbols exposed by the
library are visible; and B) for the code that is the user of the
library, without the __declspec(dllimport) on prototypes all function
calls into the library go through the import thunks rather than directly
to the __imp__foo value, an extra level of indirection. I don't know
whether A) is a concern, and B) probably shouldn't be since it's minor.
Anyway, the attached patch does this and results in what seems to be a
functioning shared library under MinGW.

Brian
--- pcre.h.in.orig    2007-04-03 08:59:51.781250000 -0700
+++ pcre.h.in    2007-04-03 10:17:58.875000000 -0700
@@ -46,23 +46,6 @@ POSSIBILITY OF SUCH DAMAGE.
 #define PCRE_PRERELEASE     @PCRE_PRERELEASE@
 #define PCRE_DATE           @PCRE_DATE@


-/* Win32 uses DLL by default; it needs special stuff for exported functions
-when building PCRE. */
-
-#ifdef _WIN32
-#  ifdef PCRE_DEFINITION
-#    ifdef DLL_EXPORT
-#      define PCRE_DATA_SCOPE __declspec(dllexport)
-#    endif
-#  else
-#    ifndef PCRE_STATIC
-#      define PCRE_DATA_SCOPE extern __declspec(dllimport)
-#    endif
-#  endif
-#endif
-
-/* Otherwise, we use the standard "extern". */
-
 #ifndef PCRE_DATA_SCOPE
 #  ifdef __cplusplus
 #    define PCRE_DATA_SCOPE     extern "C"
--- pcreposix.h.orig    2007-04-03 10:18:30.984375000 -0700
+++ pcreposix.h    2007-04-03 10:19:01.250000000 -0700
@@ -105,25 +105,6 @@ typedef struct {
   regoff_t rm_eo;
 } regmatch_t;


-/* Win32 uses DLL by default; it needs special stuff for exported functions
-when building PCRE. */
-
-#ifndef PCRE_DATA_SCOPE
-#ifdef _WIN32
-#  ifdef PCRE_DEFINITION
-#    ifdef DLL_EXPORT
-#      define PCRE_DATA_SCOPE __declspec(dllexport)
-#    endif
-#  else
-#    ifndef PCRE_STATIC
-#      define PCRE_DATA_SCOPE extern __declspec(dllimport)
-#    endif
-#  endif
-#endif
-#endif
-
-/* Otherwise, we use the standard "extern". */
-
 #ifndef PCRE_DATA_SCOPE
 #  ifdef __cplusplus
 #    define PCRE_DATA_SCOPE     extern "C"



-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
MinGW-users mailing list
MinGW-users@???

You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users


----- End forwarded message -----