[GRASS-dev] Re: ctypes problem with Vect_open_old
Glynn Clements
glynn at gclements.plus.com
Thu Jul 28 16:40:53 EDT 2011
Martin Landa wrote:
> Hi,
>
> 2011/7/23 Glynn Clements <glynn at gclements.plus.com>:
>
> [...]
>
> >> *** 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 <glynn at gclements.plus.com>
More information about the grass-dev
mailing list