Segfault происходит, когда моя общая библиотека оптимизирована с помощью icc -O3 или -O2 и используется через Python ctypes - PullRequest
4 голосов
/ 27 апреля 2011

Это странное поведение, потому что я мог не получить ошибку segfault

  • если совместно используемая библиотека была скомпилирована без или с более слабой оптимизацией (-O0 или -O1)
  • если общая библиотека была скомпилирована с помощью gcc, даже с флагом оптимизации (-O3)
  • если я запускал код из чистой программы на C (не через ctypes)

Кроме того, на некоторых машинах я не смог получить ошибку сегмента.

Если вы найдете ошибку в моем коде, это лучше, но у меня есть другие более общие вопросы:

  1. Это может быть ошибка icc или ctypes? Можно ли отправлять сообщение об ошибке в систему отслеживания ошибок, даже если я могу воспроизвести странное поведение в моей конкретной среде?
  2. Я пытался отладить код, но поскольку эта ошибка видна только при оптимизации кода, я получил много «xxx определен, но не выделен (оптимизирован)», когда я использую отладчик. Есть ли лучший способ отладки оптимизированного кода?

Как воспроизвести ошибку

Предположим, у меня есть исходный код библиотекиdd.c и скрипт python run.py, я получаю segfault с:

icc -O3 -Wall -shared strange.c -o libstrange.so
python run.py

Обратите внимание, что я мог воспроизвести эту ошибку на одной из моих машин

  • uname -m: i868
  • ОС: Ubuntu 10.04.2 LTS
  • icc: 12.0.0 20101006
  • Python: 2.6.5
  • Numpy: 1,3,0

, но не in

  • uname -m: i868
  • ОС: Ubuntu 10.10
  • icc: 12.0.3 20110309
  • Python: 2.6.6
  • Numpy: 1.3.0

или

  • uname -m: x86_64
  • ОС: Scientific Linux SL выпуск 5.5 (бор)
  • icc: 12.0.0 20101006
  • Python: 2.6.5
  • Numpy: 1.5.0b1

Код

Пожалуйста, найдите этот код здесь ( tkf / ctypes_icc / source - Bitbucket ) или ниже. Вы можете найти Makefile и скрипт оболочки для запуска программы и проверить код завершения со всеми флагами оптимизации и компиляторами (gcc и icc). Исходная версия этой программы - программа моделирования для моих исследований, но эта программа - просто бессмысленная программа.

strange.c:

typedef struct{
  int num_n;
  double dt, ie, gl, isyn, ssyn, tau1, tau2, lmd1, lmd2, k1_mean, k2_mean;
  double *vi, *v0;
} StrangeStruct;


void
func(double * v0, double * vt, double dt,
     double gl, double isyn, double ie, double isyn_estimate, int num_n)
{
  int i;
  for (i = 0; i < num_n; ++i){
    v0[i] = vt[i] + dt + gl + isyn + ie + isyn_estimate;
  }
}

int
StrangeStruct_func(StrangeStruct *self)
{
  double isyn_estimate;
  isyn_estimate =
    self->ssyn * (self->lmd1 * self->k1_mean - self->lmd2 * self->k2_mean) /
    (self->tau1 - self->tau2);
  func(self->v0, self->vi, self->dt, self->gl, self->isyn,
       self->ie, isyn_estimate, self->num_n);
  return 0;
}

run.py:

from ctypes import POINTER, pointer, c_int, c_double, Structure
import numpy

c_double_p = POINTER(c_double)


class StrangeStruct(Structure):
    _fields_ = [
        ("num_n", c_int),
        ("dt", c_double),
        ("ie", c_double),
        ("gl", c_double),
        ("isyn", c_double),
        ("ssyn", c_double),
        ("tau1", c_double),
        ("tau2", c_double),
        ("lmd1", c_double),
        ("lmd2", c_double),
        ("k1_mean", c_double),
        ("k2_mean", c_double),
        ("vi", c_double_p),
        ("v0", c_double_p),
        ]


StrangeStruct_p = POINTER(StrangeStruct)

ifnet_a2a2 = numpy.ctypeslib.load_library('libstrange.so', '.')
ifnet_a2a2.StrangeStruct_func.restype = c_int
ifnet_a2a2.StrangeStruct_func.argtypes = [StrangeStruct_p]


def func(struct):
    ifnet_a2a2.StrangeStruct_func(pointer(struct))


if __name__ == '__main__':
    ifn = StrangeStruct(
        num_n=100, dt=0.1, gl=0.1, vrest=-60, ie=-3.7, th=-40,
        ssyn=0.5, tau1=3, tau2=1,
        )
    v0 = numpy.zeros(ifn.num_n, dtype=float)
    vi = numpy.zeros(ifn.num_n, dtype=float)
    ifn.v0 = v0.ctypes.data_as(c_double_p)
    ifn.vi = vi.ctypes.data_as(c_double_p)

    func(ifn)

    v0 + vi

1 Ответ

3 голосов
/ 27 апреля 2011

Обычно невозможно смешивать двоичные файлы, скомпилированные с gcc и icc (и в этом случае python создается с помощью gcc).Вы можете попробовать использовать режим icc "gcc compatibility", который устанавливается флагом -gcc-version.Это может заставить его работать, но все же возможно, что у вас будут проблемы.

...