我正在处理一些无法编辑的遗留代码,这些代码最初是为PowerPC编译并在PowerPC上测试的。我正在尝试创建一个构建系统,它将为通用的linux盒子(Ubuntu 11.10 x64)构建。
它有一个类似cblas的自定义接口,它封装了clapack(版本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_
。然而,库需要所有数据的指针,而这个包装器当前直接传递N
、scale
和inc
的地址。这让我很害怕,因为它们是按价值传递的,而且通常是文字。
当执行mycblas_dscal
时,通常什么都不做,即a
不变或它分段。故障。使用更高的编译器优化(例如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以来包装器函数中传递值变量的地址和持久性。编译器优化会使错误行为变得更糟。我知道的不够多,无法进一步调查。有什么想法吗?
这个函数是什么
void mycblas_dscal(int N, double scale, double* data, int inc)
{
dscal_((int*) &N, (double*) &scale, data, (int*) &inc);
}
做的是声明局部变量N
、scale
和inc
并将它们的地址传递给dscal_
。由于变量是局部的,它们存在于堆栈中,一旦mycblas_dscal
完成,它们就不存在了。内部CCD_ 13通过它们的地址来操纵这些局部变量。该操作只影响局部变量,对传递给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);
}
即使用引用而不是值。
如果您不能更改它的定义,因为它是您提到的库的一部分,那么您唯一能做的就是不使用该库。我认为在这种情况下没有其他解决办法。
将数组作为指向函数的双指针传递,并使用函数中的数组地址处理数组。这可以解决你的问题。
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);
}