Problem with __gmp_expr

Ulrich Drepper drepper at
Fri Jan 17 11:28:22 UTC 2014

In C++11 there are several situations where the result of a
computation using mp?_class objects is not immediately casted to a
mp?_class type.  I haven't investigated further why this causes
problems but there are some.  Take a look at the code below, it shows
two problem cases.

You can compile the code in four ways: with and without LAMBDA
defined, with and without OK defined.  With OK defined the result of
the multiplication is forced to be of type mpq_class.  Without it the
result is of type __gmp_expr.  I've added the typeid use to show this.

Without OK defined the program crashes for me.  This might actually
vary, I guess, depending on the compiler.  valgrind shows the problem
as well:

==21979== Invalid read of size 4
==21979==    at 0x4E5713E: __gmpq_set (set.c:30)
==21979==    by 0x400AB2: main (in gmptest)
==21979==  Address 0x4 is not stack'd, malloc'd or (recently) free'd
==21979== Process terminating with default action of signal 11 (SIGSEGV)
==21979==  Access not within mapped region at address 0x4
==21979==    at 0x4E5713E: __gmpq_set (set.c:30)
==21979==    by 0x400AB2: main (in gmptest)

As you can see, a NULL pointer is used somewhere.

This is with 5.1.2 on x86-64 and i686.  From reading about the changes
in 5.1.3 it doesn't seem there have been any changes in this area.

#include <gmpxx.h>
#include <iostream>
#include <typeinfo>

mpq_class a;

  mpq_class m = a / 2;

#ifndef LAMBDA
# ifdef OK
#  define T mpq_class
# else
#  define T auto
# endif

  T i = -m * a;
  std::cout << typeid(i).name() << std::endl;
  a *= i;
# ifdef OK
#  define T -> mpq_class
# else
#  define T
# endif

  a *= [](mpq_class m) T { return -m * a; }(m);

More information about the gmp-bugs mailing list