混合fortran/C程序中的奇怪崩溃

混合fortran/C程序中的奇怪崩溃,c,fortran,C,Fortran,我正在尝试替换一组fortran程序中的一些图形代码,而不是我自己的代码。我得到了一个简单的“psvdraw”,它可以正常工作,用调用Cairo库graphic_output.C的C调用替换fortran postscript生成代码。我已经成功地解决了跨语言通话问题,没有太多麻烦 但是,当试图让第二个较大的程序“pssect”工作时,调用相同的C代码,我会出现分段错误,或者在某些情况下,程序流返回到fortran例程“error”,我不调用它,或者我的C代码中的任何fortran例程 在尝试诊

我正在尝试替换一组fortran程序中的一些图形代码,而不是我自己的代码。我得到了一个简单的“psvdraw”,它可以正常工作,用调用Cairo库graphic_output.C的C调用替换fortran postscript生成代码。我已经成功地解决了跨语言通话问题,没有太多麻烦

但是,当试图让第二个较大的程序“pssect”工作时,调用相同的C代码,我会出现分段错误,或者在某些情况下,程序流返回到fortran例程“error”,我不调用它,或者我的C代码中的任何fortran例程

在尝试诊断这个问题时,我将一组来自pssect的fortran代码链接到psvdraw的“biglib.f”,并得到了相同的错误。请注意,这些添加的代码实际上都没有被调用!错误也发生在fortan对c代码的第一次调用时。因此:链接了biglib.f的psvdraw失败,但没有链接的psvdraw成功

以下是makefile的相关部分:

生成文件 下面是被调用并产生错误的c代码的一部分:

图形输出c的一部分: 运行程序的结果
如果在未使用的代码中链接会引发问题,那么这将倾向于表明在Fortran代码或C代码中的某个地方,您正在覆盖不应该覆盖的内存。试着在Valgrind下运行编译后的程序-这将有助于确定发生这种情况的位置。

如果链接未使用的代码会触发问题,这将倾向于表明在Fortran代码或C代码中的某个地方您正在覆盖不应该覆盖的内存。试着在Valgrind下运行编译后的程序-这将有助于确定发生这种情况的位置。

我仍然怀疑Fortran和C之间的某个调用有问题,导致不一致。你是怎么打电话的?我认为最可靠的方法是使用isoc绑定来指定Fortran如何调用C例程

或者,您可以考虑具有FORTRAN接口或绑定的图形包。这样您就不必处理接口,因为Fortran调用或Fortran接口已经存在。我一直在使用迪斯林。另一种可能性是PLplot


对于当前的方法,我建议检查C例程入口的参数,以确保它们是正确的。

我仍然怀疑Fortran和C之间的某个调用存在问题,从而导致不一致。你是怎么打电话的?我认为最可靠的方法是使用isoc绑定来指定Fortran如何调用C例程

或者,您可以考虑具有FORTRAN接口或绑定的图形包。这样您就不必处理接口,因为Fortran调用或Fortran接口已经存在。我一直在使用迪斯林。另一种可能性是PLplot


对于当前的方法,我建议检查C例程入口处的参数,以确保它们是正确的。

在调试器gdb下运行应该会告诉您SEGFULT发生在哪里。使用-O0-g编译所有代码以获得准确信息。

在调试器gdb下运行应该会告诉您SEGFULT发生在哪里。使用-O0-g编译所有代码以获得准确的信息。

您使用一个参数从Fortran调用psopen,而C例程需要两个参数。也许您的Fortran编译器会在每个字符串之后添加字符串的长度作为尾随参数。或者,您第一次尝试时运气不错,只是碰巧使用了C例程在堆栈上找到的随机值。在第二种情况下,在另一种情况下,可能会发生特殊的碰撞。充其量,这是一种连接Fortran和C的不可移植方式。您可以尝试在Fortran调用中添加一个整数长度,看看会发生什么。或打印或使用调试器查看C例程入口处第二个参数的值

ISO C绑定工作得更好。它受到众多编译器的支持,例如gfortran>=4.3、ifort,并提供了连接Fortran和C的定义和可移植方式。您可以在Fortran代码中指定接口,以便Fortran编译器为C调用生成正确的指令


不过,使用已经提供Fortran接口的绘图包可能更容易。

您使用一个参数从Fortran调用psopen,而C例程需要两个参数。也许您的Fortran编译器会在每个字符串之后添加字符串的长度作为尾随参数。或者,您第一次尝试时运气不错,只是碰巧使用了C例程在堆栈上找到的随机值。在第二种情况下,在另一种情况下,可能会发生特殊的碰撞。充其量,这是一种连接Fortran和C语言的不可移植的方式 可以尝试将整数长度添加到Fortran调用中,看看会发生什么。或打印或使用调试器查看C例程入口处第二个参数的值

ISO C绑定工作得更好。它受到众多编译器的支持,例如gfortran>=4.3、ifort,并提供了连接Fortran和C的定义和可移植方式。您可以在Fortran代码中指定接口,以便Fortran编译器为C调用生成正确的指令


不过,使用已经提供Fortran接口的绘图包可能更容易。

我从make文件中注意到,您正在使用gfortran。gfortran>=4.3和gcc的组合支持isoc绑定。Fortran 2003的一部分。如果包含接口示例并使用两个参数调用psopen,那么它应该可以工作。该接口进入Fortran程序的声明,是C例程psopen的Fortran描述。不保证,因为我还没有测试过。。。字符串是一种特殊情况-您可以将Fortran程序中的定标器字符串与接口中的字符串数组相匹配,因为C参数是字符数组或指向字符的指针

interface To_psopen

   subroutine psopen ( fname, fnamelen ) bind (C, name="psopen")

      use iso_c_binding

      implicit none

      character (kind=c_char, len=1), dimension (100), intent (inout) :: fname
      integer (c_int), value, intent (in) :: fnamelen

   end subroutine psopen

end interface To_psopen

我从make文件中注意到您正在使用gfortran。gfortran>=4.3和gcc的组合支持isoc绑定。Fortran 2003的一部分。如果包含接口示例并使用两个参数调用psopen,那么它应该可以工作。该接口进入Fortran程序的声明,是C例程psopen的Fortran描述。不保证,因为我还没有测试过。。。字符串是一种特殊情况-您可以将Fortran程序中的定标器字符串与接口中的字符串数组相匹配,因为C参数是字符数组或指向字符的指针

interface To_psopen

   subroutine psopen ( fname, fnamelen ) bind (C, name="psopen")

      use iso_c_binding

      implicit none

      character (kind=c_char, len=1), dimension (100), intent (inout) :: fname
      integer (c_int), value, intent (in) :: fnamelen

   end subroutine psopen

end interface To_psopen

我添加了更多的代码。请注意,问题发生在程序执行的开始。在程序启动时,我怎么能覆盖内存呢?而且,Valgrind显然不适用于OSX 10.6。有什么建议吗?你能访问OSX 10.5机器来运行Valgrind测试吗?或者,代码是否具有足够的可移植性,可以在Linux虚拟机中编译以进行测试?我添加了更多代码。请注意,问题发生在程序执行的开始。在程序启动时,我怎么能覆盖内存呢?而且,Valgrind显然不适用于OSX 10.6。有什么建议吗?你能访问OSX 10.5机器来运行Valgrind测试吗?或者,代码是否具有足够的可移植性,可以在LinuxVM中编译以进行测试?从fortran到c只有一个调用。这个完全相同的调用在另一个程序psvdraw中工作良好。我讨厌写fortran,所以我不愿意走PLplot路线,而且,我已经完成了所有的工作;我必须全部重做。从fortran到c只有一个调用。这个完全相同的调用在另一个程序psvdraw中工作良好。我讨厌写fortran,所以我不愿意走PLplot路线,而且,我已经完成了所有的工作;我得重做一遍。我觉得自己像个白痴,因为我没有找这个。原来biglib.f有一个名为fopen…Grr的例程。正如我所说,程序流有时确实会回到fortran代码中。我以为我没有调用fortran代码,但我确实调用了,因为在retrospect中使用了愚蠢的-fno下划线编译器标志。GDB立即用回溯追踪捕捉到了它。在我通常使用XCode编码之前,我从来没有直接使用过gdb。我觉得自己是个白痴,因为我没有寻找这个。原来biglib.f有一个名为fopen…Grr的例程。正如我所说,程序流有时确实会回到fortran代码中。我以为我没有调用fortran代码,但我确实调用了,因为在retrospect中使用了愚蠢的-fno下划线编译器标志。GDB立即用回溯追踪捕捉到了它。在我通常使用XCode编码之前,我从未直接使用过gdb。
char dmh_debug = 0;

#define DEBUGPRINT(x) if (dmh_debug) {printf x;};

void psopen(char *fname, int fnamelen) {

    printf("Debug opened\n");

    char *outFileName;
    char outputType[255];
    char pageWidthString[255];
    char pageHeightString[255];

    /* Set debug status based upon presence of file named 'debug_yes' in directory */
    FILE *debugFile = fopen("debug_yes", "r");
    if (debugFile == NULL) {
        dmh_debug = 0;
    } else {
        dmh_debug = 1;
    }
    fclose(debugFile);

    dmh_debug = 1;
    DEBUGPRINT(("Debug closed\n"));

    fname[fnamelen]='\0';
    fname = trim(fname);
    outFileName = malloc((strlen(fname) + 50) * sizeof(char));
    strcpy(outFileName, fname);
    DEBUGPRINT(("Found file name:%s of length: %lu\n", fname, strlen(fname)));
[...]
pnr-rethington:source dave$ ./pssect
 Pre-PSOPEN1
Debug opened
Segmentation fault
interface To_psopen

   subroutine psopen ( fname, fnamelen ) bind (C, name="psopen")

      use iso_c_binding

      implicit none

      character (kind=c_char, len=1), dimension (100), intent (inout) :: fname
      integer (c_int), value, intent (in) :: fnamelen

   end subroutine psopen

end interface To_psopen