• valgrind leak I can't find

    From Mark Summerfield@21:1/5 to All on Thu Aug 22 08:41:46 2024
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Mark Summerfield on Thu Aug 22 11:40:31 2024
    Mark Summerfield <mark@qtrac.eu> writes:

    valgrind tells me that I have memory leaks.

    Can you post the whole code? The trouble is, with any bits missing, one
    just starts speculating about what the code might be even though you may
    know it's not relevant. The main worry is the I see no calls to free at
    all, and I don't know what happens to the v1 test vec.

    Mind you, I may not get time later to look, but I think others will want
    to see the whole code as well (if that is possible).

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Mark Summerfield on Thu Aug 22 11:07:08 2024
    Mark Summerfield <mark@qtrac.eu> wrote or quoted:
    Here is the vec_str_insert() function:

    There's a gnarly axiom among code monkeys that goes:

    If the gremlin ain't where you're scoping,
    it's kicking back somewhere else in the codebase.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Mark Summerfield on Thu Aug 22 12:01:20 2024
    On 22/08/2024 09:41, Mark Summerfield wrote:

    This is the type's struct:

    typedef struct {
    int _size;
    int _cap;
    char** _values;
    } VecStr;

    What's with the leading underscores for member names?

    It means ending with ->_ later on, which seems pointless extra clutter.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ike Naar@21:1/5 to Mark Summerfield on Thu Aug 22 11:41:50 2024
    On 2024-08-22, Mark Summerfield <mark@qtrac.eu> wrote:
    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++;
    }

    Just out of curiosity, why have special code (the vec_str_push part)
    for the case index == vec->_size, when the general code (grow, for loop etc.) would work just fine for that case?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Mark Summerfield on Thu Aug 22 12:54:07 2024
    Mark Summerfield <mark@qtrac.eu> wrote or quoted:
    vec->_values[index] = value;

    You're stashing a doppelganger of a pointer here. If this pointer
    was yanked from the heap, it'll gum up the works down the road.

    assert_alloc(p);

    Pulling the plug on a program just 'cause it bites the dust on
    a request might not always be the ticket.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Annada Behera@21:1/5 to Thiago Adams on Thu Aug 22 17:31:42 2024
    On Thu, 2024-08-22 at 08:18 -0300, Thiago Adams wrote:
    On 22/08/2024 08:01, Bart wrote:
    On 22/08/2024 09:41, Mark Summerfield wrote:

    This is the type's struct:

    typedef struct {
         int _size;
         int _cap;
         char** _values;
    } VecStr;

    What's with the leading underscores for member names?

    It means ending with ->_ later on, which seems pointless extra
    clutter.


    C++ is responsible for this.

    C++ made the usage of 'this->' optional when calling member
    functions.

    As a result, when C++ programmers encounter 'i' in the middle of a
    function, they might not know where it comes from.

    If 'this->' were not optional, 'this->i' would clarify that.

    To avoid confusion, many C++ programmers use prefixes like 'm_' that
    can't be ignored.

    Since many C programmers also work in C++, this pattern can sometimes influence C code as well.

    Although I think this is stupid thing to do when writing C, the same
    convention also exits in Python PEP-8 [1]

    _single_leading_underscore: weak “internal use” indicator.
    E.g. from M import * does not import objects whose names start with
    an underscore.

    [1]: https://peps.python.org/pep-0008/#descriptive-naming-styles

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Mark Summerfield on Thu Aug 22 15:20:24 2024
    On 2024-08-22, Mark Summerfield <mark@qtrac.eu> wrote:
    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.

    Does your program free the vector before terminating, including
    iterating over the string elements and freeing them individually?

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mark Summerfield@21:1/5 to All on Thu Aug 22 17:44:43 2024
    Thank you to all who replied.

    TL;DR The problem turned out to be a double-free because I had two owning collections with the same strings. I've now made VecStr and SetStr able to
    be owning or nonowning and this valgrind leak has gone.

    - I don't want to post the code since it is just for me relearning C.
    (I'm creating a tiny collections lib: Vec (of void*), VecStr, VecInt,
    SetInt, SetStr.)

    - The reason I special cased when index == vec->_size is that I did a
    needless premature "optimization": I no longer do this.

    - I use underscores for some struct fields. For the collections I provide
    functions for their APIs but of course the fields are not private so I use
    the underscore in a Python-like way to remind myself they are "private".

    - Yes, I free as needed:

    typedef struct {
    int _size;
    int _cap;
    char** _values;
    bool _owns; // new
    } VecStr;

    void vec_str_free(VecStr* vec) {
    assert_notnull(vec);
    vec_str_clear(vec);
    free(vec->_values);
    vec->_values = NULL;
    vec->_cap = 0;
    }

    void vec_str_clear(VecStr* vec) {
    assert_notnull(vec);
    if (vec->_owns)
    for (int i = 0; i < vec->_size; ++i)
    free(vec->_values[i]);
    vec->_size = 0;
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Mark Summerfield on Thu Aug 22 17:50:46 2024
    On 2024-08-22, Mark Summerfield <mark@qtrac.eu> wrote:
    Thank you to all who replied.

    TL;DR The problem turned out to be a double-free because I had two owning

    Is it the case that Valgrind reported the double free without stopping
    the program, but you missed it because you scrolled to the bottom for
    the leak reports? :)

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Mark Summerfield on Fri Aug 23 11:03:32 2024
    Mark Summerfield <mark@qtrac.eu> wrote or quoted:
    I don't want to post the code since it is just for me relearning C.

    It's totally your prerogative if you wanna keep your code
    on the down-low. No need to spill the beans.

    But just to cut through the fog in your logic, your "since" reasoning
    is a bit of a brain-bender: If I'm cranking out some code to sharpen
    my C chops, that's no reason to bury it six feet under later on.

    (I'm creating a tiny collections lib: Vec (of void*), VecStr, VecInt,
    SetInt, SetStr.)

    Yeah, for sure. But we got to wonder if these are really
    meat-and-potatoes C problems . . .

    Scope out what C was cooked up for in the first place. Eyeball
    those vintage UNIX source files: "find.c", "echo.c", "tar.c",
    "ls.c", "zork.c", "tail.c", and all that noise. How many of
    those kick off with a container library?

    What gnarly waves are you missing out on in efficient and
    idiomatic C programming by thinking, "I'll use my container
    library and write C like it's some Silicon Valley startup code!"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Stefan Ram on Fri Aug 23 12:18:38 2024
    On 23/08/2024 12:03, Stefan Ram wrote:
    Mark Summerfield <mark@qtrac.eu> wrote or quoted:
    I don't want to post the code since it is just for me relearning C.

    It's totally your prerogative if you wanna keep your code
    on the down-low. No need to spill the beans.

    But just to cut through the fog in your logic, your "since" reasoning
    is a bit of a brain-bender: If I'm cranking out some code to sharpen
    my C chops, that's no reason to bury it six feet under later on.

    (I'm creating a tiny collections lib: Vec (of void*), VecStr, VecInt,
    SetInt, SetStr.)

    Yeah, for sure. But we got to wonder if these are really
    meat-and-potatoes C problems . . .

    Scope out what C was cooked up for in the first place. Eyeball
    those vintage UNIX source files: "find.c", "echo.c", "tar.c",
    "ls.c", "zork.c", "tail.c", and all that noise. How many of
    those kick off with a container library?

    What gnarly waves are you missing out on in efficient and
    idiomatic C programming by thinking, "I'll use my container
    library and write C like it's some Silicon Valley startup code!"

    So, what have you done with the real Stefan Ram?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Bart on Fri Aug 23 16:26:50 2024
    On Fri, 23 Aug 2024 12:18:38 +0100
    Bart <bc@freeuk.com> wrote:

    On 23/08/2024 12:03, Stefan Ram wrote:
    Mark Summerfield <mark@qtrac.eu> wrote or quoted:
    I don't want to post the code since it is just for me relearning
    C.

    It's totally your prerogative if you wanna keep your code
    on the down-low. No need to spill the beans.

    But just to cut through the fog in your logic, your "since"
    reasoning is a bit of a brain-bender: If I'm cranking out some code
    to sharpen my C chops, that's no reason to bury it six feet under
    later on.
    (I'm creating a tiny collections lib: Vec (of void*), VecStr,
    VecInt, SetInt, SetStr.)

    Yeah, for sure. But we got to wonder if these are really
    meat-and-potatoes C problems . . .

    Scope out what C was cooked up for in the first place. Eyeball
    those vintage UNIX source files: "find.c", "echo.c", "tar.c",
    "ls.c", "zork.c", "tail.c", and all that noise. How many of
    those kick off with a container library?

    What gnarly waves are you missing out on in efficient and
    idiomatic C programming by thinking, "I'll use my container
    library and write C like it's some Silicon Valley startup code!"


    So, what have you done with the real Stefan Ram?


    It looks like real Stephan Ram hatched out of old restrictive eggshell
    few months ago.
    BTW, in order to compare his writing style of old with the new one, I
    tried to look for his posts on Google Groups. It turned out that I can
    only see citations. Posts themselves are not archived. Mysterious.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Mark Summerfield on Fri Aug 23 09:39:36 2024
    On 8/22/24 13:44, Mark Summerfield wrote:
    Thank you to all who replied.

    TL;DR The problem turned out to be a double-free because I had two owning collections with the same strings. I've now made VecStr and SetStr able to
    be owning or nonowning and this valgrind leak has gone.

    - I don't want to post the code since it is just for me relearning C.

    If you're unwilling to post the code, don't bother asking questions
    about why it's failing. The code is needed to answer the questions, so
    you're just wasting other people's time if you don't provide it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Michael S on Fri Aug 23 13:40:33 2024
    Michael S <already5chosen@yahoo.com> writes:
    On Fri, 23 Aug 2024 12:18:38 +0100
    Bart <bc@freeuk.com> wrote:

    So, what have you done with the real Stefan Ram?


    It looks like real Stephan Ram hatched out of old restrictive eggshell
    few months ago.
    BTW, in order to compare his writing style of old with the new one, I
    tried to look for his posts on Google Groups. It turned out that I can
    only see citations. Posts themselves are not archived. Mysterious.

    It is not mysterious. Herr Ram always used 'X-No-Archive:' headers
    in his posts, along with an oddball copyright notice.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Michael S on Fri Aug 23 09:39:54 2024
    On 8/23/24 09:26, Michael S wrote:
    On Fri, 23 Aug 2024 12:18:38 +0100
    Bart <bc@freeuk.com> wrote:

    On 23/08/2024 12:03, Stefan Ram wrote:
    ...
    What gnarly waves are you missing out on in efficient and
    idiomatic C programming by thinking, "I'll use my container
    library and write C like it's some Silicon Valley startup code!"

    So, what have you done with the real Stefan Ram?


    It looks like real Stephan Ram hatched out of old restrictive eggshell
    few months ago. BTW, in order to compare his writing style of old with
    the new one, I
    tried to look for his posts on Google Groups. It turned out that I can
    only see citations. Posts themselves are not archived. Mysterious.

    There's an option you can choose to prevent your messages from being
    saved; I'm not sure how it is set, and I don't remember whether it was
    Google Groups specific or applied to all usenet servers. I do know,
    however, that Stephan Ram routinely used that option, which makes
    annoying gaps in the archived conversations.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Michael S on Fri Aug 23 15:41:48 2024
    On 23/08/2024 15:26, Michael S wrote:
    On Fri, 23 Aug 2024 12:18:38 +0100
    Bart <bc@freeuk.com> wrote:



    So, what have you done with the real Stefan Ram?


    It looks like real Stephan Ram hatched out of old restrictive eggshell
    few months ago.
    BTW, in order to compare his writing style of old with the new one, I
    tried to look for his posts on Google Groups. It turned out that I can
    only see citations. Posts themselves are not archived. Mysterious.


    That could be an issue with news.eternal-september.org. They had a
    problem of some sort not long ago that resulted in messed up duplicate
    messages and lost messages.

    This new, strange Stefan Ram follows the same non-standard posting
    format as the old one, but with a completely different style of
    language. I think we may have to wait until he/it posts some code, to
    see if it is in the old Stefan's unique formatting.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to James Kuyper on Fri Aug 23 10:58:30 2024
    On 8/23/24 09:39, James Kuyper wrote:
    ...
    There's an option you can choose to prevent your messages from being
    saved; I'm not sure how it is set, and I don't remember whether it was
    Google Groups specific or applied to all usenet servers. I do know,
    however, that Stephan Ram routinely used that option, which makes
    annoying gaps in the archived conversations.

    I should have just looked at his latest message - but I wasn't sure it
    was his. The relevant feature appears to be an "Archive: no" header.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Blue-Maned_Hawk@21:1/5 to Annada Behera on Sat Aug 24 11:47:02 2024
    Annada Behera wrote:

    On Thu, 2024-08-22 at 08:18 -0300, Thiago Adams wrote:

    <snip/>

    C++ made the usage of 'this->' optional when calling member functions.

    As a result, when C++ programmers encounter 'i' in the middle of a
    function, they might not know where it comes from.

    If 'this->' were not optional, 'this->i' would clarify that.

    To avoid confusion, many C++ programmers use prefixes like 'm_' that
    can't be ignored.

    Since many C programmers also work in C++, this pattern can sometimes
    influence C code as well.

    Although I think this is stupid thing to do when writing C, the same convention also exits in Python PEP-8 [1]

    _single_leading_underscore: weak “internal use” indicator. E.g. from
    M import * does not import objects whose names start with an
    underscore.

    [1]: https://peps.python.org/pep-0008/#descriptive-naming-styles

    That's an entirely different convention that is much more common cross- linguistically. I've seen a good bit of C code that's used that for
    various parts of interfaces that need to be given separate names, but
    aren't meant to be used directly, such as identifiers constructed in the expansion of a macro. I've personally taken to the habit of naming macros
    used exclusively to get other macros to work with the name of the macro
    they're making work prefixed by a number prefixed with an underscore.



    --
    Blue-Maned_Hawk│shortens to Hawk│/blu.mɛin.dʰak/│he/him/his/himself/Mr. blue-maned_hawk.srht.site
    Made with inadequate loophole sealant!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to bluemanedhawk@invalid.invalid on Sat Aug 24 16:48:40 2024
    Blue-Maned_Hawk <bluemanedhawk@invalid.invalid> writes:
    Annada Behera wrote:


    If 'this->' were not optional, 'this->i' would clarify that.

    To avoid confusion, many C++ programmers use prefixes like 'm_' that
    can't be ignored.

    Such prefixes for structure (class) members date back to the
    earliest C compilers, where structure member names were first-class
    symbols, unqualified by the structure name (any member name could
    be used with any pointer regardless of pointer type). Thus some
    means was necessary to disambiguate member names. Remnants of
    that still exist in POSIX (e.g. the field names for struct stat
    all start with "st_").

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)