当我的共享库由icc-O3或-O2优化并通过Python ctypes使用时,就会发生Segfault

当我的共享库由icc-O3或-O2优化并通过Python ctypes使用时,就会发生Segfault,python,numpy,segmentation-fault,ctypes,icc,Python,Numpy,Segmentation Fault,Ctypes,Icc,这种行为很奇怪,因为我可以不得到错误 如果在编译共享库时未进行优化或优化程度较弱(-O0或-O1) 如果共享库是使用gcc编译的,即使使用优化标志(-O3) 如果我从纯C程序运行代码(不是通过ctypes) 此外,我无法在某些机器上找到SEG故障 如果您在我的代码中发现bug,这会更好,但我还有其他更一般的问题: 它是icc还是ctypes错误?即使我可以在我的特定环境中重现奇怪的行为,也可以将错误提交给问题跟踪系统吗 我试图调试代码,但由于此错误只有在代码优化时才可见,因此在使用调试器时,

这种行为很奇怪,因为我可以得到错误

  • 如果在编译共享库时未进行优化或优化程度较弱(-O0或-O1)
  • 如果共享库是使用gcc编译的,即使使用优化标志(-O3)
  • 如果我从纯C程序运行代码(不是通过ctypes)
此外,我无法在某些机器上找到SEG故障

如果您在我的代码中发现bug,这会更好,但我还有其他更一般的问题:

  • 它是icc还是ctypes错误?即使我可以在我的特定环境中重现奇怪的行为,也可以将错误提交给问题跟踪系统吗
  • 我试图调试代码,但由于此错误只有在代码优化时才可见,因此在使用调试器时,我得到了很多“xxx已定义但未分配(优化掉)”。有没有更好的方法来调试优化的代码
  • 如何复制错误 假设我有strange.c和hte python脚本run.py的库源代码,我会得到以下错误:

    icc -O3 -Wall -shared strange.c -o libstrange.so
    python run.py
    
    请注意,我可以在我的一台机器上复制此错误

    • uname-m
      :i868
    • 操作系统:Ubuntu 10.04.2 LTS
    • 国际商会:12.0.0 20101006
    • Python:2.6.5
    • Numpy:1.3.0
    但在

    • uname-m
      :i868
    • 操作系统:Ubuntu 10.10
    • 国际商会:12.0.3 20110309
    • Python:2.6.6
    • Numpy:1.3.0

    • uname-m
      :x86\u 64
    • OS:Scientific Linux SL 5.5版(硼)
    • 国际商会:12.0.0 20101006
    • Python:2.6.5
    • Numpy:1.5.0b1
    代码 请在此处()或下面找到代码集。 您可以找到一个Makefile和一个shell脚本来运行程序,并检查带有所有优化标志和编译器(gcc和icc)的退出代码。这个程序的原始版本是我研究的模拟程序,但这个程序只是一个毫无意义的程序

    奇怪。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;
    }
    

    通常不可能混合使用gcc和icc编译的二进制文件(在本例中,python是使用gcc构建的)。您可以尝试使用icc“gcc兼容性”模式,该模式由-gcc版本标志设置。这可能会使它起作用,但您仍有可能遇到问题。

    非常感谢!不知何故,我一直认为您可以加载使用任何编译器编译的共享库。但那怎么可能呢?也许他们在内部使用gcc?这不是加载库的问题-所有linux共享库都是elf,操作系统提供标准加载机制。它在代码本身内部。所有现代编译器都使用某种ABI,默认的ICC C++ ABI与GCC不兼容。这不仅仅限于ICC,即使不同版本的GCC使用不同的ABI,并且不兼容(例如,尝试链接GCC 3和GCC 4编译的C++代码也不起作用)。这就好像我需要通过ICC编译Python来使用ICC编译的共享库。关于最后一个问题:这是否意味着pypy和Haskel使用与gcc兼容的ABI?我不熟悉pypy和Haskel,但我认为他们不依赖gcc。
    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