Fortran 77 жалуется на общие блоки

Я использую gfortran 4.8.2 на FreeBSD 9.2 для создания исполняемых файлов. Есть три файла, один файл C и два файла Fortran 77, в которых я использую две подпрограммы с одним общим блоком.

Проблема в том, что я получаю ошибку нескольких определений от компилятора gfortran.

запросы, которые я отправил на сервер:

autoreconf
./configure
make

di8810.c

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>

void main(argc,argv)

int argc;
char *argv[];
{
  if (argc != 4)
    {
          exit(99);
    }
         gds100(argv[1],argv[2],argv[3]);
}

gds100.f

SUBROUTINE GDS100(AUSGABE,FORMAT,FILENAME)
CHARACTER*4097 EBUF   
CHARACTER*264 BUFFER      
CHARACTER*1 CBUFFER(264)      
CHARACTER*1 CEBUF(4097)      
CHARACTER*1 FORMAT


INTEGER*2 INULL      
CHARACTER*1 LTEXT(112)      
COMMON /GDSCB2/ EBUF      
EQUIVALENCE (EBUF,CEBUF(1))      
EQUIVALENCE (CEBUF(4097),INULL)     
DATA INULL /0/     
...
END

gds102.f

SUBROUTINE GDS102

CHARACTER*264 BUFFER      
CHARACTER*1 CBUFFER(264)     
CHARACTER*4097 EBUF      
CHARACTER*1 CEBUF(4097)      
INTEGER*2 INULL      
INTEGER POIADR    
COMMON /GDSCB2/ EBUF     
EQUIVALENCE (BUFFER,CBUFFER(1))      
EQUIVALENCE (EBUF,CEBUF(1))      
EQUIVALENCE (CEBUF(4097),INULL)      
DATA IWOGRZ /4096/      
DATA INULL /0/      
ENTRY GDSUMS(N)
...
END

Ошибка:

make  all-am
gcc -DHAVE_CONFIG_H -I.    -DDI88xx -g -O2 -MT src/di8810-di8810.o -MD -MP -MF src/.deps/di8810-di8810.Tpo -c -o src/di8810-di8810.o `test -f 'src/di8810.c' || echo './'`src/di8810.c
mv -f src/.deps/di8810-di8810.Tpo src/.deps/di8810-di8810.Po
gfortran -cpp  -fcheck=all -fno-underscoring  -DDI88xx -g -O2 -c -o src/di8810-gds100.o `test -f 'src/gds100.f' || echo './'`src/gds100.f
gfortran -cpp  -fcheck=all -fno-underscoring  -DDI88xx -g -O2 -c -o src/di8810-gds102.o `test -f 'src/gds102.f' || echo './'`src/gds102.f
gfortran -cpp  -fcheck=all -fno-underscoring  -DDI88xx -g -O2    -o di8810 src/di8810-di8810.o  src/di8810-gds100.o src/di8810-gds102.o
src/di8810-gds102.o: In function `gds102':
/.amd_mnt/blnn728x/home/sayik_bo/di8810_t/src/gds102.f:2: multiple definition of `gdscb2'
src/di8810-gds100.o:/.amd_mnt/blnn728x/home/sayik_bo/di8810_t/src/gds100.f:1: first defined here
collect2: Fehler: ld gab 1 als Ende-Status zurück
*** [di8810] Error code 1

Stop in /.amd_mnt/blnn728x/home/sayik_bo/di8810_t.
*** [all] Error code 1

Stop in /.amd_mnt/blnn728x/home/sayik_bo/di8810_t.

Stop in /.amd_mnt/blnn728x/home/sayik_bo/di8810_t.
*** [all] Error code 1

Stop in /.amd_mnt/blnn728x/home/sayik_bo/di8810_t.

Это сводит меня с ума. Есть идеи?


person Michael-O    schedule 22.11.2013    source источник
comment
У вас также есть функция под названием gdscb2?   -  person cup    schedule 22.11.2013
comment
Нет, только имя в общем блоке.   -  person Michael-O    schedule 22.11.2013
comment
можете ли вы сократить его до минимального кода, чтобы воспроизвести проблему. Эквивалентность 2-байтового целого числа последней позиции в массиве символов кажется странной. Затем вы инициализируете это же место отдельно в каждой подпрограмме, что тоже нечетно.   -  person agentp    schedule 23.11.2013
comment
@george, я попробую это в понедельник и сообщу. Код на самом деле работает на HP-UX и компиляторе HP Fortran, но мы пытаемся перейти на стандартную платформу (FreeBSD, Linux) в среднесрочной перспективе.   -  person Michael-O    schedule 23.11.2013
comment
@george, пожалуйста, перефразируйте ответ относительно того, что тогда вы инициализируете одно и то же место отдельно в каждой подпрограмме, что тоже странно. Я удалил DATA INULL /0/ в gds102.f и смог скомпилировать и связать. Хотя у меня другая проблема с кодом.   -  person Michael-O    schedule 25.11.2013


Ответы (1)


в доработке моего комментария

оператор common заставляет компилятор выделить глобальную память для GDSCB2.

Символы CEBUF,INULL по Equivalence по сути являются указателями на глобальное хранилище.

Теперь два оператора data inull/0/ избыточно инициализируют одно и то же место в глобальной памяти. Я не знаю, проблема это или нет.. просто что-то посмотреть.

Еще одна вещь, которую я вижу, это то, что inull составляет 2 байта (вероятно ... или, может быть, больше, но точно не 1), но он эквивалентен самому последнему байту глобального массива символов. т.е. инициализация записывает данные за пределы выделенного пространства.

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

в любом случае просто сделайте CEBUF(4097)=char(0) вместо того, чтобы использовать inull.

person agentp    schedule 26.11.2013