Программа Pro * C корректно запускается в AIX, но не в RHEL

#compilation #rhel #oracle-pro-c

#Сборник #rhel #oracle-pro-c

Вопрос:

У меня возникли некоторые проблемы с запуском двоичного файла, выполненного с помощью кода pro C. Я могу скомпилировать ее (без предупреждений) на моем новом сервере RHEL (7.8), но она зацикливается до сбоя. Я создал простой скрипт pro C для тестирования компиляции (см. Ниже). Этот скрипт легко запускается на моем предыдущем сервере AIX (6.1.0.0). База данных — Oracle 11c.

  • Клиент Oracle в AIX: …/ oracle /10.2
  • Клиент Oracle в RHEL: …/oracle/12102/cli64

Вот мой простой код, который я хочу скомпилировать и выполнить :

 #include "demo.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sqlca.h>
#include <oraca.h>

int code_erreur;
char libelle_erreur[200];

EXEC ORACLE OPTION (ORACA=YES);

EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR username[30];
    VARCHAR password[30];
    VARCHAR host[30];

    VARCHAR dynstmt[80];
    VARCHAR mData[81];

EXEC SQL END DECLARE SECTION;

int connect()
{
    printf("nConnection to %s@%sn",username.arr,host.arr);

    EXEC SQL CONNECT :username IDENTIFIED BY :password USING :host;

    printf("Connection establishedn");
    return 0;
}

void sqlerr()
{
    code_erreur = sqlca.sqlcode;
    strcpy(libelle_erreur,sqlca.sqlerrm.sqlerrmc);
    printf("SQL ERROR : %d,%s ;n", code_erreur,libelle_erreur);
    printf("sqlca.sqlerrd : %dn",sqlca.sqlerrd[2]);
}

int loadData()
{
    int lIter;

    strcpy(dynstmt.arr, "SELECT BANNER FROM V$VERSIONn");
    dynstmt.len = strlen(dynstmt.arr);

    printf("%s", (char *)dynstmt.arr);

    EXEC SQL PREPARE S FROM :dynstmt;
    EXEC SQL DECLARE lCursorData CURSOR FOR S;
    EXEC SQL OPEN lCursorData;

    for (lIter=0;lIter<10;lIter  )
    {
        EXEC SQL WHENEVER NOT FOUND DO break;
        EXEC SQL FETCH lCursorData INTO :mData;
        printf("%sn", mData.arr);
    }
    EXECL SQL CLOSE lCursorData;
    return 0;
}

void main()
{
    int lRetour=0;
    printf("Start demon");

    strcpy((char *)username.arr,"USER");
    username.len=(unsigned short)strlen((char *)username.arr);

    strcpy((char *)password.arr,"PASS");
    password.len=(unsigned short)strlen((char *)password.arr);

    strcpy((char *)host.arr,"HOST");
    host.len=(unsigned short)strlen((char *)host.arr);

    EXEC SQL WHENEVER SQLERROR do sqlerr();
    lRetour = connect();
    lRetour = loadData();

    EXEC SQL COMMIT WORK RELEASE;

    printf("End demon");
    exit(0);
}
 

Когда я ее компилирую и выполняю на своем сервере AIX, вот что я получил :

 Start demo

Connection to USER@HOST
Connection established
SELECT BANNER FROM V$VERSION
[...]
End demo
 

Но когда я компилирую ее на RHEL и выполняю, двоичный цикл выполняется до сбоя памяти :

 [...]
Connection to USER@HOST

Connection to USER@HOST

Connection to USER@HOST
Memory fault
 

Конечно, я хочу тот же результат AIX в RHEL.

Комментарии:

1. Похоже на случай перезаписи стека (или переполнения стека). Как долго фактическое значение HOST?

2. длиной 8 символов

Ответ №1:

Ваша connect функция должна быть определена как static , иначе она заменяет connect(2) библиотечную функцию libc .

 @@ -20,7  20,7 @@

 EXEC SQL END DECLARE SECTION;

-int connect()
 static int connect()
 {
     printf("nConnection to %s@%sn",username.arr,host.arr);

@@ -57,7  57,7 @@
 

Комментарии:

1. Это сработало как шарм. У вас есть идеи, почему на моем сервере AIX это сработало? Может быть, из-за устаревших объектов?

2. Разрешение внешних символов в AIX отличается. Попробуйте это: dump -X32_64 -Tv .../libclntsh.so | grep -w connect он говорит EXTref /usr/lib/libc.a(shr_64.o) connect , что это означает, что он будет использовать connect функцию из общего объекта /usr/lib/libc.a(shr_64.o) , а не из любого другого места. В Linux glibc-loader будет использовать первый доступный connect из любого места, где он его находит.