Fortran 77 обрабатывает выделение памяти в C ++ - PullRequest
2 голосов
/ 28 апреля 2011

Я пытаюсь написать программу на C ++, которая использует несколько десятков тысяч строк кода на Fortran 77, но сталкивается с некоторыми странными ошибками.Я передаю три координаты (x, y, z) и адрес трех векторов из C ++ в fortran, а затем заставляю fortran выполнять некоторые вычисления в начальных точках и возвращать результаты в трех векторах.

Я делаю это несколько сотен раз в функции C ++, оставляю эту функцию и затем возвращаюсь, чтобы сделать это снова.Он отлично работает в первый раз, но во второй раз перестает возвращать полезные результаты (возвращает nan) для точек с положительным x-компонентом.

Изначально это кажется проблемой алгоритма, за исключением трех вещей:

  1. Он отлично работает первые 200 раз, когда я его запускаю
  2. Работает, если я его вызываюиз fortran и полностью исключить C ++ (не подходит для конечной программы)
  3. Я попытался добавить операторы печати в fortran для отладки, когда она идет не так, но получается, если я добавляю инструкции печати в определенную подпрограмму (дажечто-то такое простое, как PRINT *, 'Here'), программа начинает возвращать NaN даже при первом запуске.

Вот почему я думаю, что это как-то связано с тем, как память распределяется и освобождается междуС и фортран вызовы функций / подпрограмм.Базовая настройка выглядит следующим образом: C ++: <pre> void GetPoints(void);</p> <p>extern"C" { void getfield_(float*,float*,float*,float[],float[],float[],int*,int*); }</p> <p>int main(void) { GetPoints(); //Works GetPoints(); //Doesn't }</p> <p>void GetPoints(void) { float x,y,z; int i,n,l; l=50; n=1; x=y=z=0.0; float xx[l],yy[l],zz[l] for(i=0;i<code>< l; i ++) getfield _ (& x, & y, & z, xx, yy, zz, & n, & l);// Сохраняем текущие xx, yy, zz в большом глобальном массиве}

Fortran: SUBROUTINE GETFIELD(XI,YI,ZI,XX,YY,ZZ,IIN,NP) DIMENSION XX(NP),YY(NP),ZZ(NP) EXTERNAL T89c T89c(XI,YI,ZI,XX,YY,ZZ) RETURN END<br> !In T89c.f SUBROUTINE T89c(XI,YI,ZI,XX,YY,ZZ) COMMON /STUFF/ ARRAY(100) !Lots of calculations !Calling ~20 other subroutines RETURN END

Кто-нибудь из вас видит какие-либо явные проблемы с памятью, которые ясоздание?Возможно, общие блоки, которые, как считает Фортран, существуют, но на самом деле освобождены C ++?Без возможности отладки с использованием операторов печати и времени, чтобы попытаться понять несколько тысяч строк чужого кода на Фортране 77, я готов попробовать практически все, что вы все можете предложить или придумать.

Я использую g ++ 4.5.1 для компиляции кода C ++ и окончательной компоновки, а gfortran 4.5.1 для компиляции кода фортрана.

Спасибо

** Редактировать: **

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

Ответы [ 2 ]

0 голосов
/ 29 апреля 2011

Вы должны объявить XX, YY и ZZ как массивы также в подпрограмме T89c следующим образом:

REAL*4 XX(*)    
REAL*4 YY(*)    
REAL*4 ZZ(*)

C / C ++ не должен вообще освобождать какие-либо общие блоки Фортрана. Это похоже на structs в C (то есть память резервируется во время компиляции, а не во время выполнения).

По какой-то причине gfortran, кажется, принимает следующее в T89c даже без вышеуказанных деклараций:

print *,XX(1)

во время компиляции, но при ее выполнении возникает ошибка сегментации.

0 голосов
/ 28 апреля 2011

Возможно, вы столкнулись с ошибкой "off-by-one".Массивы Fortran основаны на 1, а массивы C - 0.Убедитесь, что размеры массивов, которые вы передаете в Fortran, не на 1 меньше, чем должны быть.

Редактировать:

Я думаю, это выглядит правильно ... Тем не менее, я бы попытался выделить 51 элементФункция C ++, просто чтобы посмотреть, что происходит.

Кстати, float xx[l]; не является стандартным.Это функция gcc.Обычно вы должны выделять здесь память с new, или вы должны использовать std::vector.

Кроме того, меня смущает вызов getfield_ в цикле.Разве вы не должны передавать i на getfield_?

...