Martin Landa wrote:

> Hi,
> 
> 2011/7/23 Glynn Clements <[email protected]>:
> 
> [...]
> 
> >> *** glibc detected *** /usr/bin/python: malloc(): memory corruption:
> >> 0x09ba9fe8 ***
> >
> > Does calling G_gisinit() first change anything?
> 
> unfortunately it didn't help, still corrupted memory, now

I think I've found it. Here, vector.py has:

        # /usr/include/bits/types.h: 62
        class struct_anon_1(Structure):
            pass
        
        struct_anon_1.__slots__ = [
            '__val',
        ]
        struct_anon_1._fields_ = [
            ('__val', c_long * 2),
        ]

        __quad_t = struct_anon_1 # /usr/include/bits/types.h: 62
        ...
        __off64_t = __quad_t # /usr/include/bits/types.h: 142
        ...
        off_t = __off64_t # /usr/include/stdio.h: 93

Vect_write_line() returns an off_t. With the above definitions, this
is a structure containing a pair of 32-bit integers.

On Linux-x86, structure return values are implemented by having the
caller pass a pointer to where to store the return value as the first
(zeroth?) argument.

If I add:

        Vect_write_line.restype = c_longlong

then the script works.

The <bits/types.h> header file defines __quad_t as:

        /* quad_t is also 64 bits.  */
        #if __WORDSIZE == 64
        typedef long int __quad_t;
        typedef unsigned long int __u_quad_t;
        #elif defined __GLIBC_HAVE_LONG_LONG
        __extension__ typedef long long int __quad_t;
        __extension__ typedef unsigned long long int __u_quad_t;
        #else
        typedef struct
        {
          long __val[2];
        } __quad_t;
        typedef struct
        {
          __u_long __val[2];
        } __u_quad_t;
        #endif

I.e. as "long int" if that type is 64-bit, else "long long int" if
__GLIBC_HAVE_LONG_LONG is defined, else the structure.

__GLIBC_HAVE_LONG_LONG is defined in <features.h> as:

        /* Decide whether a compiler supports the long long datatypes.  */
        #if defined __GNUC__ \
            || (defined __PGI && defined __i386__ ) \
            || (defined __INTEL_COMPILER && (defined __i386__ || defined 
__ia64__)) \
            || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
        # define __GLIBC_HAVE_LONG_LONG 1
        #endif

And ctypesgen.py specifically undefines __GNUC__ when running the
preprocessor. (__STDC_VERSION__ is only defined if you use e.g. 
-std=c99 or -std=gnu99, not for C89)

This causes ctypes to pass an incorrect argument list for any function
which returns a 64-bit off_t, and Vect_write_line() is just such a
function.

The simplest fix is probably to add -D__GLIBC_HAVE_LONG_LONG to
CTYPESFLAGS in lib/python/ctypes/Makefile. That macro is unlikely to
be understood by anything other than glibc, and any system using glibc
is almost certain to be using a compiler which supports "long long".

However, I wouldn't be surprised if there are other situations where
undefining __GNUC__ has consequences for the ABI, but we'll just have
to deal with those as we find them.

-- 
Glynn Clements <[email protected]>
_______________________________________________
grass-dev mailing list
[email protected]
http://lists.osgeo.org/mailman/listinfo/grass-dev

Reply via email to