3

Consider the following simple code:

#include "matplotlibcpp.h"

namespace plt = matplotlibcpp;

int main() {
    plt::plot({ 1, 2, 3, 4 });
    plt::show();

    return 0;
}

It works well in Debug mode (Eclipse CDT, gcc(++17) v. 6.3.0, Win64). But when I run it in Release, the program terminates with exit value -1073741819 (even though it compiles without errors in both cases). Debugging indicates the following problem:

No source available for "_object* matplotlibcpp::detail::get_array<double>

The problem seems to be with PyArray_SimpleNewFromData appearing in the following function:

template<typename Numeric>
PyObject* get_array(const std::vector<Numeric>& v)
{
    npy_intp vsize = v.size();
    NPY_TYPES type = select_npy_type<Numeric>::type;
    if (type == NPY_NOTYPE) {
        size_t memsize = v.size()*sizeof(double);
        double* dp = static_cast<double*>(::malloc(memsize));
        for (size_t i=0; i<v.size(); ++i)
            dp[i] = v[i];
        PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, NPY_DOUBLE, dp);
        PyArray_UpdateFlags(reinterpret_cast<PyArrayObject*>(varray), NPY_ARRAY_OWNDATA);
        return varray;
    }

    PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, type, (void*)(v.data()));
    return varray;
}

in matplotlib.h.

And now to the weirdest part: I managed to "fix" it by inserting std::cout << std::endl; just before the line

PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, type, (void*)(v.data()));

Alternatively, one can write std::cout << 'a' << std::flush; (or any other character, as long as you remember to do std::flush). Curiously, without std::endl (or std::flush) the problem will persist, so it is not enough to just print some character. On the other hand, something like std::cout << std::flush; will NOT work either because it doesn't print anything.

What can be causing this problem? And why the the trick with std::endl (or std::flush) fixes it?

Additional info: gdb analysis indicates a segmentation fault:

Thread 1 received signal SIGSEGV, Segmentation fault.
0x00007ff67e889efb in matplotlibcpp::detail::get_array<double> (v=Python Exception <class 'gdb.error'>: value has been optimized out
<synthetic pointer>) at ../libs/matplotlibcpp.h:383
383         PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, type, (void*)(v.data()));

which indeed confirms that the problematic line is the line with PyArray_SimpleNewFromData.

Update: Adding import_array(); just before the problematic line seems to fix the issue (not entirely sure why). The idea was inspired by this SO question.

grjj3
  • 383
  • 2
  • 5
  • 15

0 Answers0