Path: ...!Xl.tags.giganews.com!local-4.nntp.ord.giganews.com!nntp.brightview.co.uk!news.brightview.co.uk.POSTED!not-for-mail NNTP-Posting-Date: Thu, 22 Aug 2024 08:41:46 +0000 From: Mark Summerfield Subject: valgrind leak I can't find Newsgroups: comp.lang.c MIME-Version: 1.0 User-Agent: Pan/0.154 (Izium; 517acf4) Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Message-ID: Date: Thu, 22 Aug 2024 08:41:46 +0000 Lines: 81 X-Usenet-Provider: http://www.giganews.com X-Trace: sv3-fb1Wi8NpMoO5KrJWtouNmc86quVvqJgl0gz2hmmNnP5+Ez7WCKZWdar/AgyTb61Y9lqgp6pB+/xz92j!bDnVUkcBytGbGo1bofO1Y0omqW5xibPR8mvp9jDef2JIMTQxuaE42Rjp/qZ+xvp2CzPeK/ErAjmB!OGD01GMXOIjzlXbIkPcrghpiIQ== X-Abuse-and-DMCA-Info: Please be sure to forward a copy of ALL headers X-Abuse-and-DMCA-Info: Otherwise we will be unable to process your complaint properly X-Postfilter: 1.3.40 Bytes: 3500 valgrind tells me that I have memory leaks. Its summary: valgrind ./cx_test ==18053== Memcheck, a memory error detector ==18053== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==18053== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info ==18053== Command: ./cx_test ==18053== OK 788/788 ==18053== ==18053== HEAP SUMMARY: ==18053== in use at exit: 841 bytes in 50 blocks ==18053== total heap usage: 2,323,773 allocs, 2,323,723 frees, 65,066,770 bytes allocated ==18053== ==18053== LEAK SUMMARY: ==18053== definitely lost: 841 bytes in 50 blocks ==18053== indirectly lost: 0 bytes in 0 blocks ==18053== possibly lost: 0 bytes in 0 blocks ==18053== still reachable: 0 bytes in 0 blocks ==18053== suppressed: 0 bytes in 0 blocks ==18053== Rerun with --leak-check=full to see details of leaked memory ==18053== ==18053== For lists of detected and suppressed errors, rerun with: -s ==18053== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) The first leak in the detailed report is this: ==18005== 5 bytes in 1 blocks are definitely lost in loss record 1 of 25 ==18005== at 0x48407B4: malloc (vg_replace_malloc.c:381) ==18005== by 0x49E38E9: strdup (strdup.c:42) ==18005== by 0x10CAD4: vec_str_tests (vec_str_test.c:77) ==18005== by 0x109346: main (cx_test.c:26) vec_str_test.c:77 is: vec_str_insert(&v1, 4, strdup("beta")); The reason I use strdup() is because my VecStr type takes ownership of the strings it holds. This is the type's struct: typedef struct { int _size; int _cap; char** _values; } VecStr; Here is the vec_str_insert() function: void vec_str_insert(VecStr* vec, int index, char* value) { assert_notnull(vec); assert_notnull(value); if (index == vec->_size) { // add at the end vec_str_push(vec, value); return; } assert_valid_index(vec, index); if (vec->_size == vec->_cap) vec_str_grow(vec); for (int i = vec->_size; i > index; --i) vec->_values[i] = vec->_values[i - 1]; vec->_values[index] = value; vec->_size++; } And here is the grow() function it uses: static void vec_str_grow(VecStr* vec) { const int BLOCK_SIZE = 1024 * 1024; int cap = (vec->_cap < BLOCK_SIZE) ? vec->_cap * 2 : vec->_cap + BLOCK_SIZE; char** p = realloc(vec->_values, cap * sizeof(char*)); assert_alloc(p); vec->_values = p; vec->_cap = cap; } I can't see what I've done wrong.