Re: (newbie) question concerning memory allocation

Discussion in 'C Programming' started by Eric Sosman, Sep 29, 2012.

  1. Eric Sosman

    Eric Sosman Guest

    On 9/29/2012 7:02 AM, lipska the kat wrote:
    > [...]
    > #include <stdio.h>
    > #include <stdlib.h>
    >
    > int main(int argc, char *argv[]){
    >
    > struct foo{
    > int bar;
    > long baz;
    > };
    >
    > int x = 0;
    >
    > if(argc > 1){
    > x = atoi(argv[1]);
    > }
    >
    > struct foo **foos;


    The variable `foos' is a pointer. Right now it has not been
    given a value and doesn't point at anything useful. To use `foos'
    you would first aim it at something, namely, at a `struct foo*'
    (another pointer, this one able to point at `struct foo' instances).
    But at the moment, `foos' "points at garbage."

    > struct foo **bars;
    >
    > int i;
    >
    > /* create foos*/
    > for(i = 0; i < x; i++){
    > *foos = malloc(sizeof(struct foo));


    This line asks malloc() for enough memory to hold a `struct foo',
    gets back a pointer to the allocated memory (or gets back NULL), and
    stores that memory pointer somewhere. Where? In the target `foos'
    points at. Where does `foos' point? At "garbage;" see above.

    In official parlance the effect is "undefined." A typical result
    is that the machine may fetch the value of `foos' and try to store
    the malloc() result where that garbage value points. This attempt
    might fail if the garbage in `foos' looks like a pointer to memory
    your program doesn't have write access to. But even if it "succeeds"
    all is not well: You've scribbled over some chunk of writeable memory
    and obliterated whatever it held. Did it hold something important?
    Who can say? Even if its contents were not important, is it a memory
    cell some other part of the program is about to use, obliterating
    the value you've just stored there? Who can say? Either way, your
    program is not just living on the edge, it's fallen over.

    > (*foos)->bar = i + 1;
    > (*foos)->baz = i + 2;
    > ++foos;


    It looks like you wanted to initialize `foos' to point at the
    beginning of an array of `x' (or more) memory locations that each
    can hold a `struct foo*':

    foos -> [0] -> first malloc() result
    [1] -> second malloc() result
    ...
    [x-1] -> final malloc() result

    One way to do this would be

    foos = malloc(x * sizeof(struct foo*));

    or equivalently (and usually better)

    foos = malloc(x * sizeof *foos);

    But you neglected to do any such thing, and that's probably the
    root of your trouble.

    >[...]
    > The question is, why does declaring a second pointer to the array of
    > pointers to foo cause the first pointer (foos) be be allocated an
    > unavailable memory slot.


    Undefined behavior (like trying to use the value of `foos'
    when it hasn't been assigned a value) is -- well, "undefined."
    Lots of strange things can happen, and the results need not even
    be consistent; chance is at work. Make a "trivial" or "unrelated"
    change to the program, and that may rearrange the chances and
    give you a different outcome. (See "Heisenbug.")

    --
    Eric Sosman
    d
    Eric Sosman, Sep 29, 2012
    #1
    1. Advertising

  2. Eric Sosman

    Eric Sosman Guest

    On 9/29/2012 2:18 PM, lipska the kat wrote:
    > On 29/09/12 14:03, Eric Sosman wrote:
    >> [...]
    >> One way to do this would be
    >>
    >> foos = malloc(x * sizeof(struct foo*));
    >>
    >> or equivalently (and usually better)
    >>
    >> foos = malloc(x * sizeof *foos);

    >
    > These methods all appear to require knowing the value of x at compile
    > time.


    No, just "any time before the malloc() call" suffices.

    Perhaps you imagine that `foos' somehow knows the size of
    the array it points to -- or, more exactly, the number of
    `struct foo*' pointers at and after the one it points to. That
    is not the case: `foos' points to just one `struct foo*', and it's
    up to you to know how many others are nearby. This information
    is not somehow baked into `foos' at compilation, nor at any time
    thereafter for that matter.

    > I noticed that
    >
    > int main(int argc, char *argv[])
    >
    > could also be written
    >
    > int main(int argc, char **argv)
    >
    > I suppose I was trying to reproduce this for pointers to struct foo


    Nothing wrong with that, but you missed the, um, missing link.
    You're using malloc() to get memory for the individual `struct foo'
    instances, and you've got `foos' ready to aim at a bunch of
    `struct foo*' that point to the malloc()'ed memory areas, but
    you never create the `struct foo*' pointers in the middle. In
    the crude diagram of my earlier post, you're missing the middle
    column.

    --
    Eric Sosman
    d
    Eric Sosman, Sep 29, 2012
    #2
    1. Advertising

  3. On Sat, 29 Sep 2012 19:18:03 +0100, lipska the kat
    <> wrote:

    snip

    >What I was actually trying to do was to come up with some way
    >to allow the addition of new instances of foo at runtime without
    >having to know how many I would eventually need. What I actually need is
    >a linked list, this is trivial to implement and I don't know why I
    >didn't just go for that ... trying new things hoping to discover a
    >better way of doing things I suppose, anyway ...


    Unless you need the unique features of a linked list, you could do
    this with a dynamically allocated array also. Allocate enough space
    for some initial quantity (even if it is only 1) of struct foo and
    assign the address to a pointer. When the need arises for more
    struct, use realloc() to expand the array.


    --
    Remove del for email
    Barry Schwarz, Sep 29, 2012
    #3
  4. On Sat, 29 Sep 2012 20:34:44 +0100, lipska the kat
    <> wrote:

    >On 29/09/12 19:56, Barry Schwarz wrote:
    >> On Sat, 29 Sep 2012 19:18:03 +0100, lipska the kat
    >> <> wrote:
    >>
    >> snip
    >>
    >>> What I was actually trying to do was to come up with some way
    >>> to allow the addition of new instances of foo at runtime without
    >>> having to know how many I would eventually need. What I actually need is
    >>> a linked list, this is trivial to implement and I don't know why I
    >>> didn't just go for that ... trying new things hoping to discover a
    >>> better way of doing things I suppose, anyway ...

    >>
    >> Unless you need the unique features of a linked list, you could do
    >> this with a dynamically allocated array also. Allocate enough space
    >> for some initial quantity (even if it is only 1) of struct foo and
    >> assign the address to a pointer. When the need arises for more
    >> struct, use realloc() to expand the array.

    >
    >page 252 of K and R ... interesting, OK, I'll give it a go. It will be
    >interesting to compare the overheads involved although as I understand
    >realloc it simply returns a pointer to the start of the new space.


    Page 252 is merely a description of the header file and prototypes. It
    does not tell you anything about how to use the functions safely. In
    the case of realloc for example, the result should be assigned to a
    new (possibly temporary) pointer until success has been determined.

    In any case, if realloc succeeds, not only does it return the address
    of the new space but it also copies the old data into the new space
    before releasing the old space. (If the old space was simply expanded
    to satisfy the request, then there is no need to copy, the returned
    address is the same as the old address, and no release is done.)

    --
    Remove del for email
    Barry Schwarz, Sep 29, 2012
    #4
  5. Barry Schwarz <> writes:
    > <> wrote:

    [...]
    >>page 252 of K and R ... interesting, OK, I'll give it a go. It will be
    >>interesting to compare the overheads involved although as I understand
    >>realloc it simply returns a pointer to the start of the new space.

    >
    > Page 252 is merely a description of the header file and prototypes. It
    > does not tell you anything about how to use the functions safely. In
    > the case of realloc for example, the result should be assigned to a
    > new (possibly temporary) pointer until success has been determined.


    Yes, that's generally a good idea, but it's really useful only if you
    have a fallback strategy. If your response to a realloc() failure is to
    abort the program -- or more generally if a realloc() failure means you
    no longer need access to the old data -- then you might as well assign
    the result of realloc() to the original pointer.

    > In any case, if realloc succeeds, not only does it return the address
    > of the new space but it also copies the old data into the new space
    > before releasing the old space. (If the old space was simply expanded
    > to satisfy the request, then there is no need to copy, the returned
    > address is the same as the old address, and no release is done.)


    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Sep 29, 2012
    #5
  6. Eric Sosman

    Paul N Guest

    On Sep 29, 7:18 pm, lipska the kat <> wrote:
    > What I was actually trying to do was to come up with some way
    > to allow the addition of new instances of foo at runtime without
    > having to know how many I would eventually need. What I actually need is
    > a linked list, this is trivial to implement and I don't know why I
    > didn't just go for that ... trying new things hoping to discover a
    > better way of doing things I suppose, anyway ...


    Linked lists are good for this - I use them all the time. I'd
    recommend a double linked list - each element has a pointer to the
    next element and also a pointer to the previous element. It's a bit
    more typing, but it's no harder to understand and it makes it easy to
    do some things that are messy with a singly-linked list.
    Paul N, Sep 30, 2012
    #6
  7. Eric Sosman

    Phil Carmody Guest

    lipska the kat <> writes:
    > On 30/09/12 20:21, Paul N wrote:
    >
    > [snip]
    >
    > >> What I actually need is
    > >> a linked list, this is trivial to implement and I don't know why I
    > >> didn't just go for that ... trying new things hoping to discover a
    > >> better way of doing things I suppose, anyway ...

    > >
    > > Linked lists are good for this - I use them all the time. I'd
    > > recommend a double linked list - each element has a pointer to the
    > > next element and also a pointer to the previous element. It's a bit
    > > more typing, but it's no harder to understand and it makes it easy to
    > > do some things that are messy with a singly-linked list.

    >
    > Yes, I seem to vaguely remember implementing a double linked circular
    > list in Java some years ago the 'last' element was linked with the
    > 'first' and vice versa. easy to navigate but where was the end ? |:)


    The end is just the one you (externally) have the "pointer" to.

    Phil
    --
    Regarding TSA regulations:
    How are four small bottles of liquid different from one large bottle?
    Because four bottles can hold the components of a binary liquid explosive,
    whereas one big bottle can't. -- camperdave responding to MacAndrew on /.
    Phil Carmody, Oct 10, 2012
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?RmxhY2s=?=

    Newbie question concerning page load event

    =?Utf-8?B?RmxhY2s=?=, May 17, 2005, in forum: ASP .Net
    Replies:
    3
    Views:
    507
    TDAVISJR
    May 17, 2005
  2. Ken
    Replies:
    24
    Views:
    3,862
    Ben Bacarisse
    Nov 30, 2006
  3. chris
    Replies:
    6
    Views:
    988
    chris
    Oct 28, 2005
  4. Ben Bacarisse

    Re: (newbie) question concerning memory allocation

    Ben Bacarisse, Sep 29, 2012, in forum: C Programming
    Replies:
    3
    Views:
    311
    Anand Hariharan
    Oct 10, 2012
  5. Joe Pfeiffer

    Re: (newbie) question concerning memory allocation

    Joe Pfeiffer, Sep 29, 2012, in forum: C Programming
    Replies:
    0
    Views:
    285
    Joe Pfeiffer
    Sep 29, 2012
Loading...

Share This Page