Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Re: (newbie) question concerning memory allocation

Reply
Thread Tools

Re: (newbie) question concerning memory allocation

 
 
Eric Sosman
Guest
Posts: n/a
 
      09-29-2012
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
http://www.velocityreviews.com/forums/(E-Mail Removed)d
 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      09-29-2012
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
(E-Mail Removed)d
 
Reply With Quote
 
 
 
 
Barry Schwarz
Guest
Posts: n/a
 
      09-29-2012
On Sat, 29 Sep 2012 19:18:03 +0100, lipska the kat
<(E-Mail Removed)> 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
 
Reply With Quote
 
Barry Schwarz
Guest
Posts: n/a
 
      09-29-2012
On Sat, 29 Sep 2012 20:34:44 +0100, lipska the kat
<(E-Mail Removed)> wrote:

>On 29/09/12 19:56, Barry Schwarz wrote:
>> On Sat, 29 Sep 2012 19:18:03 +0100, lipska the kat
>> <(E-Mail Removed)> 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
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      09-29-2012
Barry Schwarz <(E-Mail Removed)> writes:
> <(E-Mail Removed)> 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) (E-Mail Removed) <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"
 
Reply With Quote
 
Paul N
Guest
Posts: n/a
 
      09-30-2012
On Sep 29, 7:18*pm, lipska the kat <(E-Mail Removed)> 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.
 
Reply With Quote
 
Phil Carmody
Guest
Posts: n/a
 
      10-10-2012
lipska the kat <(E-Mail Removed)> 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 /.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: (newbie) question concerning memory allocation Ben Bacarisse C Programming 3 10-10-2012 10:15 PM
Re: (newbie) question concerning memory allocation Joe Pfeiffer C Programming 0 09-29-2012 09:48 PM
An idea for heap allocation at near stack allocation speed Bjarke Hammersholt Roune C++ 14 03-06-2011 08:07 AM
static memory allocation versus dynamic memory allocation Ken C Programming 24 11-30-2006 12:37 AM
What is the difference between dynamic memory allocation,and stack allocation ? chris C++ 6 10-28-2005 05:27 AM



Advertisments