Адрес передаваемой по значению переменной, вызывающей ошибку seg - PullRequest
0 голосов
/ 09 марта 2012

Я работаю с устаревшим кодом, который не могу редактировать, для которого изначально была скомпилирована и протестирована на PowerPC.Я пытаюсь создать систему сборки, которая будет собирать ее для универсального Linux-бокса (Ubuntu 11.10 x64).

У него есть пользовательский интерфейс, похожий на cblas, который оборачивает версию f2c универсальной библиотеки blas, включенной в clapack (Версия 3.2.1).Т.е. я компилирую liblapack, libblas и libf2c на машине linux из источника clapack и связываю его с примером следующего кода:

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) он только когда-либо работает.faults.

Чтобы проверить библиотеку 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);
}

Мое единственное понимание - это что-то, связанное с адресом и постоянством переменных передачи по значению вфункция-обертка с сег.Поведение сбоя ухудшается с оптимизацией компилятора.Я не знаю достаточно, чтобы расследовать дальше.Есть идеи?

Ответы [ 2 ]

0 голосов
/ 09 марта 2012

Передайте массив как двойной указатель на функцию и обработайте массив, используя адрес массива в функции.Это может решить вашу проблему.

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); 
} 
0 голосов
/ 09 марта 2012

Что это за функция

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. Внутренний dscal_ управляет этими локальными переменными через их адрес. Эта манипуляция влияет только на локальные переменные, она не влияет на исходные переменные, переданные в mycblas_dscal. Как только вы включите оптимизацию, я думаю, что вызов mycblas_dscal будет встроенным , что еще больше усугубит проблему и вызовет ошибки сегмента.

Если вы можете изменить mycblas_dscal, измените его следующим образом:

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

т.е.. используйте ссылки, а не значения.

Если вы не можете изменить его определение, потому что оно является частью той библиотеки, которую вы упомянули, то единственное, что вы можете сделать, это не использовать эту библиотеку. Я не думаю, что есть какое-то другое решение в этом случае.

...