ошибка сегментации (дамп ядра) в python с помощью swig, но он работает, когда я меняю имя переменной - PullRequest
2 голосов
/ 21 июня 2019

Я использую Python с Swig. Файл cpp содержит переменную int step=0; и функция использует переменную void test(); Я получаю ошибку сегментации, когда я вызываю функцию в Python. Но после того, как я изменил имя переменной на step2, она работает.

Версия: Swig 4.0.0 питон 3.6.7

Получается ошибка сегментации:

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. получить ошибку сегментации

$ 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)

Но я меняю только имя переменной:

#include<iostream>

int step2 = 0;

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

После перекомпиляции работает.

$ 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
>>> 

Как я могу избежать такого рода ошибок?

1 Ответ

1 голос
/ 24 июня 2019

Похоже, корень вашей проблемы в том, что step экспортируется из libc, по крайней мере, на нескольких общих системах, поэтому у вас возникло глобальное столкновение пространства имен.

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

(Этофункция, мне было немного интересно, для чего она нужна, поскольку она мне не знакома - оказывается, это связано с обработкой регулярных выражений и поиском следующего совпадения скомпилированного регулярного выражения в строковом буфере)

Самое простое решение этой проблемы в вашем конкретном примере - сделать вместо вашей глобальной переменной step значение static (или использовать анонимное пространство имен):

#include<iostream>

static int step = 0;

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

Этого достаточно, чтобы исправить ваш пример.

Хорошей практикой является проверка того, что все глобальные переменные являются статическими, если вы действительно не хотите их экспортировать, особенно при создании общего объекта (например, модуля Python).

Вы также можете использовать gcc-fvisibility=hidden по умолчанию скрывать, а не экспортировать глобальные переменные.(SWIG правильно гарантирует, что вещи, которые нужно экспортировать, все еще видны, даже если это установлено).

...