导致seg-fault的pass-by-value变量的地址

时间:2012-03-09 03:12:26

标签: c++ segmentation-fault pass-by-value lapack blas

我正在使用一些我无法编​​辑的遗留代码,这些代码最初是在PowerPC上编译和测试的。我正在尝试创建一个构建系统,为通用Linux机箱(Ubuntu 11.10 x64)构建它。

它有一个类似于cblas的自定义界面,它包含了clapack(Ver.3.2.1)中包含的通用blas库的f2c版本。即我从clapack源代码在linux机器上编译liblapack,libblas和libf2c,并将它与以下示例代码链接起来:

int main()
{
    double a[3] = {100,200,300};
    // Scale all elements of a by 0.1
    // This uses a custom wrapper that seg. faults
    mycblas_dscal(3,0.1,a,1);
}

void mycblas_dscal(int N, double scale, double* data, int inc)
{
    dscal_((int*) &N, (double*) &scale, data, (int*) &inc);
}

mycblas_dscal只需调用blas库实现dscal_。但是,库需要指向所有数据的指针,此包装器目前直接传递Nscaleinc的地址。这让我感到害怕,因为它们是按价值传递的,而且往往是文字。

执行时mycblas_dscal通常不执行任何操作,即a不变或为seg。故障。使用更高的编译器优化(例如gcc -O3),它只能进行seg。故障。

要测试blas库,以下代码可以正常工作:

int main()
{
    // This calls the library directly and works fine but I cannot edit 
    //the rest of the code which is using the wrapped version above.
    int size = 3;
    double scale = 0.1;
    int inc = 1;
    dscal_(&size,&scale,a,&inc);
}

我唯一的见解是与seg之后的包装函数中的值传递值变量的地址和持久性有关。编译器优化会使错误行为变得更糟。我不知道进一步调查。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

这个功能

void mycblas_dscal(int N, double scale, double* data, int inc)
{
    dscal_((int*) &N, (double*) &scale, data, (int*) &inc);
}

确实是声明局部变量Nscaleinc并将其地址传递给dscal_。由于变量是本地变量,因此它们存在于堆栈中,并在mycblas_dscal完成后停止存在。内部dscal_通过其地址操纵这些局部变量。该操作仅影响局部变量,它对传递给mycblas_dscal的原始变量没有影响。启用优化后,我猜mycblas_dscal调用内联,进一步恶化问题并导致seg错误。

如果您可以更改 mycblas_dscal,请按以下步骤进行更改:

void mycblas_dscal(int &N, double &scale, double*& data, int &inc)
{
    dscal_((int*) &N, (double*) &scale, data, (int*) &inc);
}

即。使用引用而不是值。

如果您无法更改其定义,因为它是您提到的库的一部分,那么您唯一能做的就是不使用该库。在这种情况下,我认为没有任何其他解决方案。

答案 1 :(得分:0)

将数组作为双指针传递给函数,并使用函数中的数组地址处理数组。这可以解决你的问题。

int main() 
{
    double a[3] = {100,200,300};
    // Scale all elements of a by 0.1
    // This uses a custom wrapper that seg. faults     
    mycblas_dscal(3,0.1,&a,1); 
}  

void mycblas_dscal(int N, double scale, double** data, int inc) 
{     
   dscal_((int*) &N, (double*) &scale, *data, (int*) &inc); 
}