Ниже приведен пример кода из 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;
}