segmentation fault(core dumped) in python with swig, but it works when I change the variable name

Viewed 1466

I'm using python with swig. The cpp file contains a variable int step=0; and a function use the variable void test(); I get a segmentation fault when I call the function in python. But after I change the variable name to step2, it works.

Version: swig 4.0.0 python 3.6.7

This get a segmentation fault:

1.ex.cpp

#include<iostream>

int step = 0;

void test(){
    step += 1;
    printf("ok\n");
}

2.ex.i

%module ex

%inline %{
    extern void test();
%}

3.run

swig -c++ -python ex.i
g++ -fPIC -c ex.cpp -c ex_wrap.cxx -I/home/lzhang/venv/include/python3.6m
g++ -shared ex.o ex_wrap.o -o _ex.so

4.get a segmentation fault

$ python
Python 3.6.7 (default, Oct 22 2018, 11:32:17) 
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ex
>>> ex.test()
Segmentation fault (core dumped)

But I only change variable name:

#include<iostream>

int step2 = 0;

void test(){
    step2 += 1;
    printf("ok\n");
}

After recompile, it works.

$ python
Python 3.6.7 (default, Oct 22 2018, 11:32:17) 
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ex
>>> ex.test()
ok
>>> 

How can I avoid this kind of error?

1 Answers

The root of your problem seems to be that step is exported from libc, at least on a bunch of common systems, so you've got a global namespace colision.

nm -D /lib/arm-linux-gnueabihf/libc-2.28.so|grep step
000c5210 W step

(It's a function, I was a bit curious about what it's for since it's not one I'm familiar with - turns out it's something to do with regex processing and finding the next match of a compiled regex in a string buffer)

The simplest solution to this in your specific example is to make your global variable step be static (or use an anonymous namespace) instead:

#include<iostream>

static int step = 0;

void test(){
    step += 1;
    printf("ok\n");
}

This is sufficient to fix your example.

It's good practice to make sure all global variables are static unless you really want to be exporting them, particularly so when building a shared object (e.g. a Python module).

You can also use gcc's -fvisibility=hidden to default to hiding rather than exporting global variables. (SWIG correctly makes sure things which need to be exported are still visible even when this is set).

Related