On Fri, 2013-08-16 at 14:22 +0200, Tobias Oetiker wrote: > Hi Svante, > > > > OK, I will continue next with rrd_client.c. Is that one built into the > > library librrd*.so* ? > > yes, but it can also be used standalone
How? > > One issue with rrd_client:get_path is the const definitions. In order to > > free the dynamically allocated strings, to avoid memory leaks const has > > to be abandoned in some places. OK? > > I can only tell you when I see the patch ... Attached below is a stripped down example from rrd_client.c. Defining NOT_CONST in the code and gcc -g -Wall test_get_path.c valgrind --leak-check=full ./a.out . gives: valgrind --leak-check=full ./a.out . ==5155== Memcheck, a memory error detector ==5155== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. ==5155== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info ==5155== Command: ./a.out . ==5155== calling rrd_create rrdc_create: filename=. filename=. get_path: path=. absfilename=/my/path/to/rrdtool/rrdtool-git rc = 0 (0=OK) ==5155== ==5155== HEAP SUMMARY: ==5155== in use at exit: 0 bytes in 0 blocks ==5155== total heap usage: 1 allocs, 1 frees, 4,096 bytes allocated ==5155== ==5155== All heap blocks were freed -- no leaks are possible ==5155== ==5155== For counts of detected and suppressed errors, rerun with: -v ==5155== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) However uncommenting #undef NOT_CONST results in a small memory leak: ==5190== ==5190== HEAP SUMMARY: ==5190== in use at exit: 4,096 bytes in 1 blocks ==5190== total heap usage: 1 allocs, 0 frees, 4,096 bytes allocated ==5190== ==5190== 4,096 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==5190== at 0x4C28BED: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5190== by 0x4E6F5F7: realpath@@GLIBC_2.3 (canonicalize.c:79) ==5190== by 0x400842: get_path (test_get_path.c:46) ==5190== by 0x400905: rrdc_create (test_get_path.c:83) ==5190== by 0x400983: rrd_create (test_get_path.c:107) ==5190== by 0x4009F7: main (test_get_path.c:124) ==5190== ==5190== LEAK SUMMARY: ==5190== definitely lost: 4,096 bytes in 1 blocks ==5190== indirectly lost: 0 bytes in 0 blocks ==5190== possibly lost: 0 bytes in 0 blocks ==5190== still reachable: 0 bytes in 0 blocks ==5190== suppressed: 0 bytes in 0 blocks ==5190== ==5190== For counts of detected and suppressed errors, rerun with: -v ==5190== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4) Heap usage it OK in both cases. What do you think, should the memory-leak-free version be used for patching rrd_client.c (I have problems to test this directly, see above)
#include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <pthread.h> static char *sd_path = "/tmp"; /* cache the path for sd */ static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; /* Defines if the returned path is const or not */ #define NOT_CONST 1 #undef NOT_CONST /* get_path: Return a path name appropriate to be sent to the daemon. * * When talking to a local daemon (thru a UNIX socket), relative path names * are resolved to absolute path names to allow for transparent integration * into existing solutions (as requested by Tobi). Else, absolute path names * are not allowed, since path name translation is done by the server. * * One must hold `lock' when calling this function. */ #ifdef NOT_CONST static char *get_path (const char *path) /* {{{ */ #else static const char *get_path (const char *path) /* {{{ */ #endif { #ifdef NOT_CONST char *ret = (char *)path; #else const char *ret = path; #endif int is_unix = 0; printf("get_path: path=%s\n", path); if ((path == NULL) || (sd_path == NULL)) return (NULL); if ((*sd_path == '/') || (strncmp ("unix:", sd_path, strlen ("unix:")) == 0)) is_unix = 1; if (is_unix) { ret = realpath(path, NULL); if (ret == NULL) printf("realpath(%s): %s\n", path, strerror(errno)); return ret; } else { if (*path == '/') /* not absolute path */ { printf("absolute path names not allowed when talking " "to a remote daemon\n"); return NULL; } } #ifdef NOT_CONST return (char *)path; #else return path; #endif } /* }}} char *get_path */ int rrdc_create (const char *filename) { #ifdef NOT_CONST char *absfilename; #else const char *absfilename; #endif if (filename == NULL) { printf("rrdc_create: no filename specified\n"); return (-1); } else printf("rrdc_create: filename=%s\n", filename); pthread_mutex_lock (&lock); printf("filename=%s\n", filename); absfilename = get_path (filename); printf("absfilename=%s\n", absfilename); if (absfilename == NULL) { pthread_mutex_unlock (&lock); return (-1); } pthread_mutex_unlock (&lock); /* Cannot be freed if using const */ #ifdef NOT_CONST free(absfilename); #endif return(0); } int rrd_create( int argc, char **argv) { int rc; optind = 0; // option handling rc = rrdc_create (argv[optind]); printf("rc = %d (0=OK)\n",rc); return rc; } int main( int argc, char *argv[]) { if (argc != 2) { printf("error: option argument missing\n"); return(1); } if (argv[1]) { printf("calling rrd_create\n"); rrd_create(argc - 1, &argv[1]); } else { printf("error: return\n"); return(1); } return (0); }
_______________________________________________ rrd-developers mailing list rrd-developers@lists.oetiker.ch https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers