GnuCobol使用double类型的参数调用C函数

qgzx9mmu  于 2023-10-16  发布在  其他
关注(0)|答案(2)|浏览(127)

我有两个C函数做同样的事情。唯一的区别是它们的返回类型和第一个参数类型:

int func1(int a, int *b) {
    if (a > 0) {
        *b = 0;
        return 1;
    }

    *b = -1;
    return 0;
}

double func2(double a, int *b) {
    if (a > (double)0.0) {
        *b = 0;
        return 1.0;
    }

    *b = -1;
    return (double)0.0;
}

将它们编译到库中:

gcc -c -static -o testlib.o testlib.c

下面的COBOL代码调用这两个函数:

IDENTIFICATION DIVISION.
       PROGRAM-ID. CallCFunctions.
       
       ENVIRONMENT DIVISION.

       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  VAR-AI USAGE BINARY-SHORT SIGNED.
       01  VAR-BI USAGE BINARY-SHORT SIGNED.
       01  VAR-CI USAGE BINARY-SHORT SIGNED.
       
       01  VAR-AD USAGE BINARY-DOUBLE.
       01  VAR-BD USAGE BINARY-DOUBLE.
       01  VAR-CD USAGE BINARY-DOUBLE.
       

       PROCEDURE DIVISION.
           
           MOVE 1 TO VAR-AI.
           MOVE -10 TO VAR-BI.
           MOVE ZERO TO VAR-CI.
           CALL "func1" USING BY VALUE VAR-AI BY REFERENCE VAR-BI
               RETURNING VAR-CI
           DISPLAY "Calling 'func1'".
           DISPLAY "A = ", VAR-AI, " B = ", VAR-BI, " C = ", VAR-CI

           MOVE 1 TO VAR-AD.
           MOVE -10 TO VAR-BD.
           MOVE ZERO TO VAR-CD.
           CALL "func2" USING BY VALUE VAR-AD BY REFERENCE VAR-BD
               RETURNING VAR-CD
           DISPLAY "Calling 'func2'".
           DISPLAY "A = ", VAR-AD, " B = ", VAR-BD, " C = ", VAR-CD

       STOP RUN.

编译COBOL代码:

cobc -x -free -o test test.cbl testlib.o

第一个函数工作,但第二个生成错误:
尝试引用未分配的内存(信号SIGSEGV)满输出

Calling 'func1'
A = +00001 B = +00000 C = +00001
Calling 'func2'

attempt to reference unallocated memory (signal SIGSEGV)

有谁能解释一下是什么问题吗?

uqdfh47h

uqdfh47h1#

您在COBOL源代码中声明的变量类型(USAGE)与C源代码中的变量类型不兼容。
首先,GnuCobol中的BINARY-DOUBLE类型是一个64位的原生integer。从GnuCOBOL程序员指南:
二进制-双[签名]

        数值范围:2019 - 09 - 22 00:00:00 00:00
        存储格式:原生二进制文件
如果您想要IEEE-754 64位浮点类型(如C `double`),则需要`FLOAT-LONG`。同一份文件:
浮长
~~~~~~~~~~
        数值范围:电话:+86-10 - 88888888传真:+86-10 - 88888888
        存储格式:本机IEEE 754 Binary 64浮点
然而,我看不出这本身会导致报告的`SIGSEGV`错误,因为两个内存“单元”具有相同的大小(尽管传递的`a`值将被解释为无意义的`double`)。
更有可能导致内存冲突的是`int`参数的类型也是错误的:`BINARY-SHORT`是一个**16位**整数,但C `int`是**32位**(参见同一链接文档)。
您需要:
1.在COBOL代码中使用`BINARY-LONG`(或`BINARY-INT`)类型;
1.或者在C代码中使用`short`类型作为参数和返回类型。
就目前而言,您的C函数正在向一个只能保证大小为16位的位置写入(或 * 尝试 * 写入)32位;这是**undefined behavior**,更可能是错误的原因。[您只是(不)幸运,在`func1`调用中,UB没有触发内存冲突!]
kdfy810k

kdfy810k2#

我已经离开Cobol 23年了,在这一点上只了解C的基础知识.
并试图分配负数。(移动-10到VAR-BD。)在过去,这最终会导致存储问题。

相关问题