LINUX.ORG.RU

ibase.h ничего не понимаю :(


0

0

Падает программма :( . Выполняется, и в момент выхода из функции 
умирает с Segmentation fault'ом . Коннект к базе проходит успешно,
в цикле выводятся на экран данные(все правильно), далее подходит к выходу
функции и там Segmntation fault; 

Т.е. резалт выглядит так :
Starting...
<data>
last_instraction_before segmentation fault
Segmentation fault.

Сама ф-ция приведенна ниже. main выглядит примерно так : 
int main ()
{
    std::cout << "Starting..." << flush;
    std::vector<sTPT> rez;
    my_func ( rez );
    std::cout << "ok" << endl;
    return 0;
}

#include <ibase.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <strings.h>
#include "base_func.h"

#define SQL_VARCHAR(len) struct {short length; char text[(len)+1];}
#define SQL_INT struct{long data;}

void my_func ( std::vector<sTPT> &rez )
{
    isc_expand_dpb ( &dpb, &dpb_length, isc_dpb_user_name,user_name, isc_dpb_password, user_password, NULL );

    isc_attach_database ( status_vector, path_to_base.size(), ( char *) path_to_base.c_str(),&db, dpb_length, dpb );

    if ( base_have_error ( status_vector, tr_handle, db ) )
        return;

    isc_start_transaction ( status_vector, &tr_handle, 1, &db, sizeof ( tpb ) , tpb );

    if ( base_have_error ( status_vector, tr_handle, db ) )
        return;

    XSQLDA *osqlda;
    isc_stmt_handle stmt = NULL;
    char str_stmt[128] = {0};
    int param = 165;
    sprintf ( str_stmt, "select * from my_query ( %d )", param );

    osqlda = ( XSQLDA * ) malloc ( XSQLDA_LENGTH ( 4 ) );
    osqlda->version = SQLDA_VERSION1;
    osqlda->sqln = 4;
    osqlda->sqld = 4;

    isc_dsql_allocate_statement ( status_vector, &db, &stmt );

    isc_dsql_prepare ( status_vector, &tr_handle,
            &stmt, 0, str_stmt, 1, NULL );

    isc_dsql_describe ( status_vector, &stmt, 1, osqlda );

    SQL_VARCHAR(128) param;    SQL_INT id;
    SQL_VARCHAR(128) name;     SQL_INT time;

    osqlda->sqlvar[0].sqltype = SQL_VARYING;
    osqlda->sqlvar[0].sqldata = (char *) &param;
    osqlda->sqlvar[1].sqltype = SQL_LONG;
    osqlda->sqlvar[1].sqldata =  ( char * ) &id;
    osqlda->sqlvar[2].sqltype = SQL_VARYING;
    osqlda->sqlvar[2].sqldata = (char *) &name;
    osqlda->sqlvar[3].sqltype = SQL_LONG;
    osqlda->sqlvar[3].sqldata =  ( char * ) &time;

    isc_dsql_execute ( status_vector, &tr_handle, &stmt, 1, osqlda );

    while ( ( fetch_stat = isc_dsql_fetch ( status_vector, &stmt, 1, osqlda ) )  == 0 )
    {
        sTPT buf;
        buf.param = std::string(param.text, param.length);
        std::cout << buf.param << endl;
        buf.id    = id.data;
        std::cout << id.data << endl;
        buf.name  = std::string (name.text, name.length);
        std::cout << buf.name << endl;
        buf.time  = time.data;
        std::cout << time.data << endl;
        rez.push_back ( buf );
    }
    if ( fetch_stat == 100L )
    {
        if ( base_have_error ( status_vector, tr_handle, db ) )
        {
            return;
        }
    }

    isc_commit_transaction ( status_vector, &tr_handle );
    isc_detach_database ( status_vector, &db );
    isc_dsql_free_statement ( status_vector, &stmt, DSQL_drop );

    for ( int i = 0 ; i < Xc ; i++ )
        free ( osqlda->sqlvar[i].sqldata );
    free ( osqlda );

    std::cerr << "last_instraction_before segmentation fault" << endl;
}
anonymous

Ты случаем 
   free(dpb) не делаешь?, 
надо
   isc_free(dpb)

По идее, после 
   isc_dsql_describe ( status_vector, &stmt, 1, osqlda );
надо убедится, что 
   sqlda->sqld == 4 --- в результате 4 поля,

а так же после isc_dsql_describe поле sqltype уже имеет значение, и нужно писать не
   osqlda->sqlvar[0].sqltype = SQL_VARYING
а
   if ( osqlda->sqlvar[0].sqltype != SQL_VARYING ) "ВЫХОД с ошибкой";

и если sqltype нечетное число (nullable полу), то нужно в 
   osqlda->sqlvar[0].sqlind занести указатель на short.
И если значение поля будет NULL, то по этому указателю запишется 1.

ИМХО цикл
for ( int i = 0 ; i < Xc ; i++ )
   free ( osqlda->sqlvar[i].sqldata );
это что то страшное, что такое Xc, что такое SQL_INT, можно ли 
переопределять переменную:
    int param = 165;
    SQL_VARCHAR(128) param;

Можешь попробовать для начала убрать все free, потому что если вызвать
free() на неправильный указатель, запросто получить segmentation fault




mky ★★★★★
()
Ответ на: комментарий от mky

Спасибо ОГРОМНОЕ за советы. Щас буду пробовать...

anonymous
()
Ответ на: комментарий от mky

>надо isc_free(dpb)
сделал
>надо убедится, что sqlda->sqld == 4 --- в результате 4 поля
убедился действительно 4
>for ( int i = 0 ; i < Xc ; i++ ) free ( osqlda->sqlvar[i].sqldata );
убрал
>что такое SQL_INT
#define SQL_INT struct{long data;}
>можно ли переопределять переменную: 
>int param = 165; SQL_VARCHAR(128) param;
это очепятка на самом деле int sparam;
>if ( osqlda->sqlvar[0].sqltype != SQL_VARYING ) "ВЫХОД с ошибкой";
сделал - оказалось что osqlda->sqlvar[0].sqltype == SQL_VARYING + 1
и если не поменять на SQL_VARYING , то после execut'a
Dynamic SQL Error
-SQL error code = -804
-Incorrect values within SQLDA structure

Помогите пожалуйста разобраться почему?

anonymous
()
Ответ на: комментарий от anonymous

>сделал - оказалось что osqlda->sqlvar[0].sqltype == SQL_VARYING + 1
>и если не поменять на SQL_VARYING , то после execut'a
>Dynamic SQL Error
>-SQL error code = -804
>-Incorrect values within SQLDA structure

и если sqltype нечетное число (nullable полу), то нужно в
   osqlda->sqlvar[0].sqlind занести указатель на short.
И если значение поля будет NULL, то по этому указателю запишется 1.

то есть 
short flags[4];
if ( osqlda->sqlvar[0].sqltype % 2 ) 
         osqlda->sqlvar[0].sqlind[0] = flags;
и так далее для всех полей (flags + 1, ...)

после isc_dsql_fetch() делаем проверку на null значене поля в БД
  if ( osqlda->sqlvar[0].sqltype % 2 && flags[0] < 0 ) 
     "Вывод что поле имеет значени null"

Здесь null это не Си указатель на 0, а поле БД в неопределенном состоянии.

P.S. Есть C++ библиотека ibpp (обертка на libgds). Функциональности меньше, но если программа на C++ ibpp использовать проще, чем gds.


mky ★★★★★
()
Ответ на: комментарий от mky

Еще раз спасибо. Но short f0 = 0; Результат выполнения ... if ( osqlda->sqlvar[0].sqltype % 2 ) osqlda->sqlvar[0].sqlind[0] = f0; был segmentation fault.

Я поменял на osqlda->sqlvar[0].sqlind = &f0; Результат успешный и теперь не нужно указывать явно SQL_VARYING. После fetch() поставил проверку if ( osqlda->sqlvar[0].sqltype % 2 && f0 < 0 ) { cerr << "Pole 0 NULL." << endl; return; } Условие ни разу не выполнилось ни для одного поля т.е. для sqlvar[1], 2 и 3; Но после выхода из ф-ции все равно segmentation fault;

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

anonymous
()
Ответ на: комментарий от mky

Спасибо ОГРОМНОЕ !!! ibpp очень удобная обертка!!!

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.