LINUX.ORG.RU

[С/C++] Очистка данных после memcpy


0

0

Ниже приведен пример кода из DBD::Oracle, перлового модуля. Т.к. знания у меня по Си можно сказать никакие, вопросы по очистке данных после memcpy:

1. Куда записываются данные на самом деле в случае memcpy(fb_ary->cb_abuf+imp_sth->piece_size*(fb_ary->piece_count), void *src, size n) в функции fetch_clbk_lob?

2. Как это очистить правильно? Т.к. имеются проблемы: первое неоправданно большое выделение памяти (получаемые данные 120 кБ, выделяемая память 32Мб). Более того, при повторном запросе память заново выделяется.

sb4
presist_lob_fetch_cbk(dvoid *octxp, OCIDefine *dfnhp, ub4 iter, dvoid **bufpp,
                      ub4 **alenpp, ub1 *piecep, dvoid **indpp, ub2 **rcpp)
{
    dTHX;
    imp_fbh_t   *fbh =(imp_fbh_t*)octxp;
    fb_ary_t    *fb_ary;
    fb_ary  = fbh->fb_ary;
    *bufpp  = (dvoid *) fb_ary->abuf;
    *alenpp = &fb_ary->bufl;
    *indpp  = (dvoid *) fb_ary->aindp;
    *rcpp   = fb_ary->arcode;


    if (dbd_verbose >= 5 ) {
        PerlIO_printf(DBILOGFP, " In presist_lob_fetch_cbk\n");
    }

    if ( *piecep ==OCI_NEXT_PIECE ){/*more than one piece*/

        memcpy(fb_ary->cb_abuf+fb_ary->piece_count*fb_ary->bufl,fb_ary->abuf,fb_ary->bufl );
    /*as we will be using both blobs and clobs we have to use
      pointer arithmetic to get the values right.  in this case we simply
      copy all of the memory of the buff into the cb buffer starting
      at the piece count * the  buffer length
      */

        fb_ary->piece_count++;/*used to tell me how many pieces I have, Might be able to use aindp for this?*/

    }


    return OCI_CONTINUE;

}


void
ora_free_fbh_contents(imp_fbh_t *fbh)
{
    dTHX;
    if (fbh->fb_ary) {
        fb_ary_free(fbh->fb_ary);
        fbh->fb_ary = NULL;
    }
    sv_free(fbh->name_sv);
    if (fbh->desc_h)
        OCIDescriptorFree_log(fbh->desc_h, fbh->desc_t);
    if (fbh->obj)
        Safefree(fbh->obj);
    if (fbh->parmdp)
        OCIDescriptorFree_log(fbh->parmdp, OCI_DTYPE_PARAM);

}


void
fb_ary_free(fb_ary_t *fb_ary)
{
    Safefree(fb_ary->abuf);
    Safefree(fb_ary->aindp);
    Safefree(fb_ary->arlen);
    Safefree(fb_ary->arcode);
    Safefree(fb_ary->cb_abuf);
    Safefree(fb_ary);

}

typedef struct fb_ary_st fb_ary_t;  /* field buffer array   */
struct fb_ary_st {  /* field buffer array EXPERIMENTAL  */
    ub4             bufl;       /* length of data buffer        */
    ub4             cb_bufl;    /* length of piece of data fetched in callback.*/
    ub4             piece_count;/*# of pieces retrieved*/
    sb2             *aindp; /* null/trunc indicator variable    */
    ub1             *abuf;      /* data buffer (points to sv data)  */
    ub1             *cb_abuf;   /*yet another buffer for picewise callbacks this means I only need to allocate memory once a prepare rather than at each fetch*/
    ub2             *arlen; /* length of returned data      */
    ub2             *arcode;    /* field level error status     */
};


static int
fetch_clbk_lob(SV *sth, imp_fbh_t *fbh,SV *dest_sv){

    dTHX;
    D_imp_sth(sth);
    fb_ary_t *fb_ary = fbh->fb_ary;

    ub4 actual_bufl=imp_sth->piece_size*(fb_ary->piece_count)+fb_ary->bufl;

    if (fb_ary->piece_count==0){
        if (DBIS->debug >= 6 || dbd_verbose >= 6 )
            PerlIO_printf(DBILOGFP,"  Fetch persistent lob of %d (char/bytes) with callback in 1 piece of %d (Char/Bytes)\n",actual_bufl,fb_ary->bufl);

        memcpy(fb_ary->cb_abuf,fb_ary->abuf,fb_ary->bufl );

    } else {
            if (DBIS->debug >= 6 || dbd_verbose >= 6 )
            PerlIO_printf(DBILOGFP,"  Fetch persistent lob of %d (Char/Bytes) with callback in %d piece(s) of %d (Char/Bytes) and one piece of %d (Char/Bytes)\n",actual_bufl,fb_ar

        memcpy(fb_ary->cb_abuf+imp_sth->piece_size*(fb_ary->piece_count),fb_ary->abuf,fb_ary->bufl );
    }

    if (fbh->ftype == SQLT_BIN){
        *(fb_ary->cb_abuf+(actual_bufl))='\0'; /* add a null teminator*/
        sv_setpvn(dest_sv, (char*)fb_ary->cb_abuf,(STRLEN)actual_bufl);
    } else {
        sv_setpvn(dest_sv, (char*)fb_ary->cb_abuf,(STRLEN)actual_bufl);
        if (CSFORM_IMPLIES_UTF8(fbh->csform) ){
            SvUTF8_on(dest_sv);
        }
    }
    return 1;
}

1. В fb_ary->cb_abuf.
2. memcpy память не выделяет, а просто копирует байты. Где здесь выделяется память под fb_ary->cb_abuf я не нашел.

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

Safefree — какая-то внутренняя функция модуля, нужно смотреть ее реализацию.

Deleted
()

в случае memcpy(fb_ary->cb_abuf+imp_sth->piece_size*(fb_ary->piece_count), void *src, size n)

в роли К.О. и Лор-отладчика, осмелюсь предположить, что данные записываются в последний элемент 'плоского' массива fb_ary->cb_abuf. Каждый элемент которого строго следует за предыдущим и имеет фиксированный размер imp_sth->piece_size. Сам массив в свою очередь передаётся косвенно через как элемент структуры (заголовка чего-то-там imp_fbh_t *) и память под который выделена заранее, по логике не приведённой в отрывке кода.

в общем на вторую часть вопроса (а именно какого хрена выделено столько памяти, действительно ли она выделенна и как её освобождать) по коду ответить нельзя.

зы. С-функции (методы С++) в которых больше 4-х параметров, мягко говоря не приветствуются

зыы. к спецам Oracle и знатокам perl сие не относится :)

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