Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #162476
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Newsgroups | comp.lang.c |
| Subject | Re: Freeing a dynamically allocated array of structs within a struct in C |
| Date | 2021-08-29 17:17 +0100 |
| Organization | A noiseless patient Spider |
| Message-ID | <87h7f86x9j.fsf@bsb.me.uk> (permalink) |
| References | <1348a974-54cd-47cf-bf40-7034feaa1f78n@googlegroups.com> |
Bithov Vinu Student <vinub@calday.co.uk> writes:
> I have the following definition:
>
> ```
> typedef struct {
> char* entry_key;
> char* entry_value;
> } deck_entry;
> ```
>
> And the following function to parse a string into a deck_entry:
>
> ```
> deck_entry* parse_deck_entry(char* to_parse) {
> char* string_to_parse = strdup(to_parse);
> char* a = strsep(&string_to_parse, ": ");
> char* b = strsep(&string_to_parse, "\n");
> return make_deck_entry(a, b);
> }
> ```
>
> With the test code as follows:
>
> ```
> int main() {
> deck_entry* new_deck = parse_deck_entry("Age: 23\n");
> free_deck_entry(new_deck);
> return 0;
> }
> ```
>
> The program works without segfaulting or anything else, in fact, using
> a diagnostic function I wrote (print_deck_entry) all the information
> has been parsed properly with the write formatting, etc. However,
> running through Valgrind shows:
>
> ```
> ==8494== Memcheck, a memory error detector
> ==8494== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
> ==8494== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
> ==8494== Command: ./box
> ==8494==
> ==8494==
> ==8494== HEAP SUMMARY:
> ==8494== in use at exit: 25 bytes in 1 blocks
> ==8494== total heap usage: 4 allocs, 3 frees, 65 bytes allocated
> ==8494==
> ==8494== LEAK SUMMARY:
> ==8494== definitely lost: 25 bytes in 1 blocks
> ==8494== indirectly lost: 0 bytes in 0 blocks
> ==8494== possibly lost: 0 bytes in 0 blocks
> ==8494== still reachable: 0 bytes in 0 blocks
> ==8494== suppressed: 0 bytes in 0 blocks
> ==8494== Rerun with --leak-check=full to see details of leaked memory
> ==8494==
> ==8494== For lists of detected and suppressed errors, rerun with: -s
> ==8494== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
> ```
>
> Modifying parse_deck_entry to be the following:
>
> ```
> deck_entry* parse_deck_entry(char* to_parse) {
> char* string_to_parse = strdup(to_parse);
> char* a = strsep(&string_to_parse, ": ");
> char* b = strsep(&string_to_parse, "\n");
> deck_entry* tmp = make_deck_entry(a, b);
> free(a);
> free(b);
> free(string_to_parse);
> return tmp;
> }
> ```
First off (and I know it's not really the answer to your question), you
can only pass to free a pointer returned by malloc (or calloc or
realloc), and you must free that pointer only once.
strdup (not a standard C function) returns a pointer from malloc and 'a'
probably holds an identical pointer value to 'string_to_parse' so this
code has two errors: the malloc'd storage is freed twice, and a pointer
that was not returned by malloc (the value in 'b') is passed to free.
> ...will still compile but prints the following when run:
>
> ```
> free(): invalid pointer
> Aborted (core dumped)
> ```
>
> I can't imagine anything else that could be causing a memory leak,
> considering parse_deck_entry() is the only function I've written that
> is being called in the test code. What have I done wrong and what
> could I do to improve?
The leak is indeed the 9 bytes allocated to the copy of "Age: 23\n" and
the 16 bytes used by the allocated struct.
The real problem is that you must free this storage only when it is not
needed. If you free it in parse_deck_entry you can't use the entry for
anything -- the storage has already gone.
Most programs free the storage after they have finished working with
it. For many programs, that is just before main returns, and there are
many people who will advise you not to both if that is your situation as
every sensible OS will free the storage when you program finished.
But I am no one of them! Programs can become sub-programs, and making
sure that you free all allocated storage is not hard and will make
re-using part of this program on others much less error prone.
> Stability and memory-safety are pretty huge for what I'm writing, even
> though I am writing in C (rather than Rust, etc.)
Out of interest, why did you choose C?
(And kudos for posting a clear question with all the data needed to give
a reasonable stab as a reply. It's less common than you might think.)
--
Ben.
Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
Freeing a dynamically allocated array of structs within a struct in C Bithov Vinu Student <vinub@calday.co.uk> - 2021-08-29 08:34 -0700
Re: Freeing a dynamically allocated array of structs within a struct in C Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2021-08-29 15:43 +0000
Re: Freeing a dynamically allocated array of structs within a struct in C Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2021-08-29 16:12 +0000
Re: Freeing a dynamically allocated array of structs within a struct in C Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-09-06 05:46 -0700
Re: Freeing a dynamically allocated array of structs within a struct in C Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-08-29 17:17 +0100
Re: Freeing a dynamically allocated array of structs within a struct in C Bonita Montero <Bonita.Montero@gmail.com> - 2021-08-29 20:01 +0200
Re: Freeing a dynamically allocated array of structs within a struct in C Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2021-08-29 18:21 +0000
Re: Freeing a dynamically allocated array of structs within a struct in C Bonita Montero <Bonita.Montero@gmail.com> - 2021-08-29 20:34 +0200
Re: Freeing a dynamically allocated array of structs within a struct in C Bonita Montero <Bonita.Montero@gmail.com> - 2021-08-30 09:01 +0200
Re: Freeing a dynamically allocated array of structs within a struct in C Robert Latest <boblatest@yahoo.com> - 2021-08-31 05:44 +0000
Re: Freeing a dynamically allocated array of structs within a struct in C Kaz Kylheku <563-365-8930@kylheku.com> - 2021-08-31 07:50 +0000
Re: Freeing a dynamically allocated array of structs within a struct in C Bonita Montero <Bonita.Montero@gmail.com> - 2021-08-31 10:59 +0200
Re: Freeing a dynamically allocated array of structs within a struct in C Bonita Montero <Bonita.Montero@gmail.com> - 2021-08-30 09:45 +0200
Re: Freeing a dynamically allocated array of structs within a struct in C Bonita Montero <Bonita.Montero@gmail.com> - 2021-08-30 10:15 +0200
Re: Freeing a dynamically allocated array of structs within a struct in C Kaz Kylheku <563-365-8930@kylheku.com> - 2021-08-29 18:14 +0000
Re: Freeing a dynamically allocated array of structs within a struct in C Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2021-08-29 18:18 +0000
Re: Freeing a dynamically allocated array of structs within a struct in C Barry Schwarz <schwarzb@delq.com> - 2021-08-29 11:44 -0700
Re: Freeing a dynamically allocated array of structs within a struct in C Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2021-08-29 19:04 +0000
Re: Freeing a dynamically allocated array of structs within a struct in C Barry Schwarz <schwarzb@delq.com> - 2021-08-29 14:15 -0700
Re: Freeing a dynamically allocated array of structs within a struct in C scott@slp53.sl.home (Scott Lurndal) - 2021-08-29 21:19 +0000
Re: Freeing a dynamically allocated array of structs within a struct in C Barry Schwarz <schwarzb@delq.com> - 2021-08-29 18:14 -0700
Re: Freeing a dynamically allocated array of structs within a struct in C Bonita Montero <Bonita.Montero@gmail.com> - 2021-08-30 18:27 +0200
Re: Freeing a dynamically allocated array of structs within a struct in C Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2021-08-30 16:17 +0000
Re: Freeing a dynamically allocated array of structs within a struct in C James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-08-30 14:14 -0400
Re: Freeing a dynamically allocated array of structs within a struct in C Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-08-30 11:39 -0700
Re: Freeing a dynamically allocated array of structs within a struct in C James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-08-31 10:08 -0400
Re: Freeing a dynamically allocated array of structs within a struct in C Kaz Kylheku <563-365-8930@kylheku.com> - 2021-09-01 04:40 +0000
Re: Freeing a dynamically allocated array of structs within a struct in C Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-09-01 00:57 -0700
Re: Freeing a dynamically allocated array of structs within a struct in C Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2021-08-30 19:16 +0000
Re: Freeing a dynamically allocated array of structs within a struct in C Manfred <noname@add.invalid> - 2021-08-30 21:49 +0200
Re: Freeing a dynamically allocated array of structs within a struct in C "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-08-30 12:49 -0700
Re: Freeing a dynamically allocated array of structs within a struct in C scott@slp53.sl.home (Scott Lurndal) - 2021-08-30 22:31 +0000
Re: Freeing a dynamically allocated array of structs within a struct in C Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-09-30 07:04 -0700
Re: Freeing a dynamically allocated array of structs within a struct in C Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-08-29 15:38 -0700
Re: Freeing a dynamically allocated array of structs within a struct in C Manfred <noname@add.invalid> - 2021-08-30 14:21 +0200
Re: Freeing a dynamically allocated array of structs within a struct in C Bonita Montero <Bonita.Montero@gmail.com> - 2021-08-30 18:29 +0200
Re: Freeing a dynamically allocated array of structs within a struct in C Bart <bc@freeuk.com> - 2021-08-30 18:30 +0100
Re: Freeing a dynamically allocated array of structs within a struct in C Bonita Montero <Bonita.Montero@gmail.com> - 2021-08-31 04:22 +0200
csiph-web