El objetivo es detectar los memory leaks y la idea es que ademas de detectarlos sepamos en que archivo y en que línea están. Para ello hay que compilar con la opcion -g para ver el código fuente para cada funcion en el stack trace.
En las entradas anteriores de detección de memory leak (I y II) se recomendó setear las variables de ambiente LD_PRELOAD y LD_AUDIT en el .profile, dbx no funcionará adecuadamente si éstas 2 variables estan seteadas.
Ejemplo paso a paso: (Código fuente del archivo basic_mta.c y del Makefile al final del post)
- Remover las variables de ambiente LD_PRELOAD y LD_AUDIT.
unset LD_PRELOAD unset LD_AUDIT
- Compilar utilizando la opción -g (en el Makefile del ejemplo nuestro programa se llamará basic_mta) y si no estamos compilando con gcc usar tambien la opción -O o la opcion -xO[n]
make clobber all
- Ejecutar dbx con nuestro ejecutable como parámetro:
dbx basic_mta
- En caso de que nuestro ejecutable reciba parámetros por línea de comandos:
dbx -c "runargs -param1 valor1 -parm2 valor2" basic_mta
- Ya dentro del dbx ejecutar:
check -memuse
dbxenv rtc_mel_at_exit verbose dbxenv rtc_error_log_file_name errores.txt
run
- Al finalizar la ejecución del programa en caso de haber memory leaks veremos algo así:
- En el resultado de la ejecución podemos ver el call stack de la memoria que se esta perdiendo y asi poder corregir nuestro memory leak.
Memory Leak (mel): Found leaked block of size 16 bytes at address 0x65658 At time of allocation, the call stack was: [1] _alloc_result_header() (optimized), at 0xe75aad9c (line ~367) in "pin_decimal.c" [2] pin_decimal_set_scale() (optimized), at 0xe75ae960 (line ~3545) in "pin_decimal.c" [3] pin_decimal_from_double() (optimized), at 0xe75aca28 (line ~1719) in "pin_decimal.c" [4] pbo_decimal_from_double() (optimized), at 0xe75a8bd0 (line ~165) in "pbo_decimal.c" [5] pin_mta_worker_opcode() (optimized), at 0x15628 (line ~243) in "basic_mta.c"
- Ahí se ve el nombre del archivo(basic_mta.c) y la línea(243) donde esta el memory leak.
- Para ver el resto de los memory leaks hay que revisar el resto de los links en la solapa Memory leaks.
Makefile
OS=solaris VERSION=7.5 ########## PINDIR=${PIN_HOME} INCDIR=$(PINDIR)/include LIBDIR=$(PINDIR)/lib ########## CC_comp_solaris = cc CC_link_solaris = CC CC_comp_linux = gcc CC_link_linux= gcc CC_comp_hpux_ia64 = cc CC_link_hpux_ia64 = $(CC_comp_hpux_ia64) CC_comp_hpux = cc CC_link_hpux = $(CC_comp_hpux) CC_comp_aix = xlc_r CC_link_aix = $(CC_comp_aix) CC_comp = $(CC_comp_$(OS)) CC_link = $(CC_link_$(OS)) ########## CFLAGS_solaris= -g -xcg92 -O CFLAGS_linux= -m32 -fPIC -g -pthread CFLAGS_hpux_ia64= +Z CFLAGS_hpux= -g -Ae +Z CFLAGS_aix= -g -Drs6000 -Dunix -D__unix -D__aix CFLAGS= $(CFLAGS_$(OS)) CPPFLAGS = -I$(INCDIR) LDFLAGS_solaris= -R:$(LIBDIR): LDFLAGS_linux= -m32 -Wl,--export-dynamic LDFLAGS_hpux_ia64= -Wl,-E -Wl,+b:$(LIBDIR): LDFLAGS_hpux= -Wl,-E -Wl,+b:$(LIBDIR): LDFLAGS_aix=-bM:SRE -bexpall -brtl -lc LDFLAGS = -L$(LIBDIR) $(LDFLAGS_$(OS)) OS_LIBS_solaris= -lsocket -lnsl -lgen -lposix4 -lpthread -ldl OS_LIBS_hpux_ia64= -lsec -lrt -lpthread -lCsup -lunwind OS_LIBS_hpux= -lsec -lrt -lpthread -lCsup OS_LIBS_aix= -lpthread OS_LIBS_linux= -lpthread LDLIBS= -lportal -lmta -lpinsys $(OS_LIBS_$(OS)) ########## INCFILES= $(INCDIR)/pcm.h $(INCDIR)/pin_mta.h $(INCDIR)/pin_bill.h \ $(INCDIR)/pin_cust.h $(INCDIR)/pin_act.h \ $(INCDIR)/pin_errs.h $(INCDIR)/pinlog.h ########### APPS= basic_mta FILES= basic_mta.c OBJECTS= basic_mta.o DEP_linux=$(FILES) DEP=$(DEP_$(OS)) ########### all: $(APPS) clean: rm -f $(OBJECTS) core clobber: clean rm -f $(APPS) ########### $(APPS): $(OBJECTS) $(INCFILES) Makefile $(CC_link) -o $@ $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(OBJECTS) $(LDLIBS) $(OBJECTS): $(INCFILES) Makefile $(DEP) $(CC_comp) -c $(CFLAGS) $(CPPFLAGS) $(FILES) ########### FRC:
basic_mta.c
#include <stdio.h> #include <time.h> #include "pcm.h" #include "pin_errs.h" #include "pinlog.h" #include "pin_pymt.h" #include "pin_mta.h" /******************************************************************* * Configuration of application * Called prior MTA_CONFIG policy opcode *******************************************************************/ PIN_EXPORT void pin_mta_config( pin_flist_t *param_flistp, pin_flist_t *app_flistp, pin_errbuf_t *ebufp) { int32 mta_flags = 0; void *vp = NULL; if (PIN_ERR_IS_ERR(ebufp)) { return; } PIN_ERR_LOG_FLIST (PIN_ERR_LEVEL_DEBUG, "pin_mta_config parameters flist", param_flistp); PIN_ERR_LOG_FLIST (PIN_ERR_LEVEL_DEBUG, "pin_mta_config application info flist", app_flistp); vp = PIN_FLIST_FLD_GET (app_flistp, PIN_FLD_FLAGS, 0,ebufp); if(vp) mta_flags = *((int32*)vp); /*********************************************************** * The new flag MTA_FLAG_VERSION_NEW has been introduced to * differentiate between new mta & old mta applications as * only new applications have the ability to drop PIN_FLD_PARAMS * for valid parameters . It is only for new apps that * checking err_params_cnt is valid, otherwise for old applications * this check without a distincion for new applications would hamper * normal functioning. ***********************************************************/ mta_flags = mta_flags | MTA_FLAG_VERSION_NEW; mta_flags = mta_flags | MTA_FLAG_BATCH_MODE; PIN_FLIST_FLD_SET (app_flistp, PIN_FLD_FLAGS, &mta_flags, ebufp); if (PIN_ERR_IS_ERR(ebufp)) { PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR, "pin_mta_config error", ebufp); } } /******************************************************************* * Usage information for the specific app. * Called prior MTA_USAGE policy opcode *******************************************************************/ PIN_EXPORT void pin_mta_usage( char *prog) { pin_errbuf_t ebuf; pin_flist_t *ext_flistp = NULL; char *usage_str = NULL; char *format = "\nModo de uso:\t %s\n"; PIN_ERRBUF_CLEAR (&ebuf); usage_str = (char*)pin_malloc( strlen(format) + strlen(prog) + 1 ); if (usage_str == NULL) { PIN_ERR_LOG_MSG(PIN_ERR_LEVEL_ERROR,"No Memory error"); return; } sprintf(usage_str, format ,prog); ext_flistp = pin_mta_global_flist_node_get_no_lock(PIN_FLD_EXTENDED_INFO, &ebuf); PIN_FLIST_FLD_SET (ext_flistp, PIN_FLD_DESCR, usage_str, &ebuf); printf("%s \n", usage_str); if (PIN_ERR_IS_ERR(&ebuf)) { PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR, "pin_mta_usage error", &ebuf); } pin_free(usage_str); } /******************************************************************* * Application defined search criteria. * Called prior MTA_INIT_SEARCH policy opcode *******************************************************************/ PIN_EXPORT void pin_mta_init_search( pin_flist_t *app_flistp, pin_flist_t **s_flistpp, pin_errbuf_t *ebufp) { pin_flist_t *s_flistp = NULL; char *template = "select x from /account where F1 in ('ROOT') "; int32 search_flag = 768; poid_t *poid = NULL; void *vp = NULL; pin_flist_t *tmp_flistp = NULL; if (PIN_ERR_IS_ERR(ebufp)) { return; } PIN_ERR_LOG_FLIST (PIN_ERR_LEVEL_DEBUG, "pin_mta_init_search application info flist", app_flistp); s_flistp = PIN_FLIST_CREATE(ebufp); poid = PIN_FLIST_FLD_GET (app_flistp, PIN_FLD_POID_VAL, 0, ebufp); PIN_FLIST_FLD_PUT(s_flistp, PIN_FLD_POID, PIN_POID_CREATE(PIN_POID_GET_DB(poid), "/search/pin", -1, ebufp), ebufp); PIN_FLIST_FLD_SET (s_flistp, PIN_FLD_FLAGS, &search_flag, ebufp); PIN_FLIST_FLD_SET (s_flistp, PIN_FLD_TEMPLATE, template, ebufp); tmp_flistp = PIN_FLIST_ELEM_ADD (s_flistp, PIN_FLD_ARGS, 1, ebufp); PIN_FLIST_FLD_SET (tmp_flistp, PIN_FLD_ACCOUNT_NO, "", ebufp); tmp_flistp = PIN_FLIST_ELEM_ADD (s_flistp, PIN_FLD_RESULTS, 0, ebufp); PIN_FLIST_FLD_SET (tmp_flistp, PIN_FLD_ACCOUNT_NO, "", ebufp); if (PIN_ERR_IS_ERR(ebufp)) { PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR, "pin_mta_init_search error", ebufp); PIN_FLIST_DESTROY_EX (&s_flistp, NULL); }else{ *s_flistpp = s_flistp; PIN_ERR_LOG_FLIST (PIN_ERR_LEVEL_DEBUG, "pin_mta_init_search search flist", s_flistp); } } /******************************************************************* * Search results may be updated, modified or enriched * Called prior MTA_TUNE policy opcode *******************************************************************/ PIN_EXPORT void pin_mta_tune( pin_flist_t *app_flistp, pin_flist_t *srch_res_flistp, pin_errbuf_t *ebufp) { pin_const_poid_type_t type = 0; pin_cookie_t s_cookie = 0; pin_cookie_t m_cookie = 0; pin_flist_t *multi_res_flistp = NULL; pin_flist_t *tmp_flistp = NULL; poid_t *pdp = 0; poid_t *n_pdp = 0; int64 db = 0; int64 id = 0; int32 i = 0; int32 s_rec_id = 0; int32 m_rec_id = 0; void *vp = 0; if (PIN_ERR_IS_ERR(ebufp)) { return; } PIN_ERR_LOG_FLIST (PIN_ERR_LEVEL_DEBUG, "basic_mta application info flist", app_flistp); PIN_ERR_LOG_FLIST (PIN_ERR_LEVEL_DEBUG, "basic_mta search results flist", srch_res_flistp); vp = PIN_FLIST_FLD_GET (app_flistp, PIN_FLD_OPS_ERROR, MTA_OPTIONAL, ebufp); if(vp){ i = *((int32*)vp); } if (i) { while((multi_res_flistp = PIN_FLIST_ELEM_GET_NEXT(srch_res_flistp, PIN_FLD_MULTI_RESULTS, &s_rec_id, 1, &s_cookie, ebufp)) != NULL) { m_cookie = 0; while((tmp_flistp = PIN_FLIST_ELEM_GET_NEXT(multi_res_flistp, PIN_FLD_RESULTS, &m_rec_id, 1, &m_cookie, ebufp)) != NULL) { vp = PIN_FLIST_FLD_TAKE (tmp_flistp, PIN_FLD_POID, 0, ebufp); if(vp) { pdp = (poid_t*)vp; db = PIN_POID_GET_DB (pdp); id = PIN_POID_GET_ID (pdp); type = PIN_POID_GET_TYPE (pdp); id = id * i; n_pdp = PIN_POID_CREATE (db, type,id, ebufp); PIN_POID_DESTROY (pdp, ebufp); PIN_FLIST_FLD_PUT (tmp_flistp, PIN_FLD_POID, n_pdp, ebufp); } } } } if (PIN_ERR_IS_ERR(ebufp)) { PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR, "pin_mta_tune error", ebufp); } } /******************************************************************* * Function executed at application exit * Called prior MTA_EXIT policy opcode *******************************************************************/ PIN_EXPORT void pin_mta_exit( pin_flist_t *app_flistp, pin_errbuf_t *ebufp) { PIN_ERR_LOG_FLIST (PIN_ERR_LEVEL_DEBUG, "pin_mta_exit application info flist", app_flistp); if (PIN_ERR_IS_ERR(ebufp)) { PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR, "pin_mta_exit error", ebufp); printf("Error durante la ejecucion.\n"); } else { printf("Ejecucion exitosa.\n"); } } /******************************************************************* * Main application opcode is called here *******************************************************************/ PIN_EXPORT void pin_mta_worker_opcode( pcm_context_t *ctxp, pin_flist_t *srch_res_flistp, pin_flist_t *op_in_flistp, pin_flist_t **op_out_flistpp, pin_flist_t *ti_flistp, pin_errbuf_t *ebufp) { pin_cookie_t cookie = NULL; pin_flist_t *app_flistp = NULL; int32 rec_id = 0; int32 mta_flags = 0; void *vp = NULL; if (PIN_ERR_IS_ERR(ebufp)) { return; } app_flistp = pin_mta_global_flist_node_get_with_lock (PIN_FLD_APPLICATION_INFO, ebufp); vp = PIN_FLIST_FLD_GET (app_flistp, PIN_FLD_FLAGS, 0,ebufp); if(vp){ mta_flags = *((int32*)vp); } pin_mta_global_flist_node_release(PIN_FLD_APPLICATION_INFO, ebufp); //memory leak agregado a proposito pin_decimal_t *amount = pbo_decimal_from_double(90, ebufp); //memory leak agregado a proposito poid_t *poid = PIN_POID_CREATE(1, "/account", -1, ebufp); //memory leak agregado a proposito pin_flist_t *tmp_flistp = PIN_FLIST_COPY(op_in_flistp, ebufp); //memory leak agregado a proposito char *str = (char*)malloc(sizeof(char)); }
Martín Falconi
No hay comentarios.:
Publicar un comentario