#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
из любого места, где он его находит.