Para ello utilizaremos otra herramienta: discover.
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 se recomendó setear las variables de ambiente LD_PRELOAD y LD_AUDIT en el .profile, Discover 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
- Instrumenter el binario con discover utilizando las opciones deseadas (discover -? nos mostrará todas las opciones disponibles)
discover -E 100 -f -m -w resultado.txt -H resultado.html -v basic_mta
- Ejecutar nuestro programa normalmente.
basic_mta
- Revisar los archivos generados en busca de errores o memory leaks (en este ejemplo resultado.txt y resultado.html ). Ambos archivos (txt y html) contienen la misma información, por lo que generar ambos es redundante (lo hice a modo de ejemplo), en este ejemplo solo revisaré el arhivo resultado.html.
- Abrimos el archivo html y vemos 3 pestañas (Errors, Warnings y Memory leaks).En este ejemplo nos centraremos en la de Memory leaks:

- Como se observa en la imagen hay varios memory leaks, al hacer clic en los links se mostrará el stack trace y si se compiló con la opción se puede ver el código fuente de cada función con solo hacer clic en la función:

- Ahí se ve el nombre del archivo y la línea 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.
- Para ver más en detalle la explicación de los reportes generados consultar la documentacón oficial de discover.
Observación:
Si al momento de instrumentar el binario nos da un error con las librerías:
pin> discover -E 100 -f -m -w resultado.txt -H resultado.html -v basic_mta
discover (info): Sun Memory Error Discovery Tool 2.0 SunOS_sparc 2010/08/13
discover (info): Prepared binary /export/home/pines/pin14/7.5/lib/libportal.so
discover (info): Prepared binary /export/home/pines/pin14/martin/memory/mta/basic_mta
discover (info): Instrumenting target /export/home/pines/pin14/7.5/lib/libportal.so
discover: error: Cannot accomodate new program headers in the file
Realizar la instrumentación con la opcion -l (lite):
pin>discover -E 100 -f -m -w resultado.txt -H resultado.html -v -l basic_mta
discover (info): Sun Memory Error Discovery Tool 2.0 SunOS_sparc 2010/08/13
discover (info): Prepared binary /export/home/pines/pin14/martin/memory/mta/basic_mta
discover (info): Instrumenting target /export/home/pines/pin14/martin/memory/mta/basic_mta
discover (info): Instrumented file output: basic_mta.
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