Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

Dynamic Arrays: Using malloc() and realloc()

dynamic array realloc malloc array

  • Please log in to reply
41 replies to this topic

#13 dcs

dcs

    CC Devotee

  • Just Joined
  • PipPipPipPipPipPip
  • 730 posts

Posted 05 November 2009 - 01:32 PM

[COLOR="red"]data[/COLOR]=realloc([COLOR="red"]data[/COLOR],(i+2)*sizeof(int));

Avoid this idiom. Use a temporary.
  • 0

#14 Guest

Guest

    CC Devotee

  • Expert Member
  • PipPipPipPipPipPip
  • 914 posts
  • Location:USA
  • Programming Language:C, Java, Python, Bash, Others
  • Learning:Assembly, Scheme

Posted 05 November 2009 - 03:17 PM

Can you explain why I should use a temporary?
  • 0
Root Beer == System Administrator's Beer
Download the new operating system programming kit! (some assembly required)

#15 dcs

dcs

    CC Devotee

  • Just Joined
  • PipPipPipPipPipPip
  • 730 posts

Posted 06 November 2009 - 09:13 AM

Can you explain why I should use a temporary?

Did you follow the link? If realloc fails, you leak the original memory.
  • 0

#16 WingedPanther73

WingedPanther73

    A spammer's worst nightmare

  • Moderator
  • 17757 posts
  • Location:Upstate, South Carolina
  • Programming Language:C, C++, PL/SQL, Delphi/Object Pascal, Pascal, Transact-SQL, Others
  • Learning:Java, C#, PHP, JavaScript, Lisp, Fortran, Haskell, Others

Posted 06 November 2009 - 09:14 AM

If the realloc fails, you just lost your handle on the data.
  • 0

Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

My MineCraft server site: http://banishedwings.enjin.com/


#17 psam

psam

    CC Regular

  • New Member
  • PipPipPip
  • 35 posts

Posted 15 November 2009 - 04:56 AM

Great tutorial.
But what's with the goto? You can simply use:
else
{
	free(data);
	printf("Not enough memory!\n");
	return 1;
}
Right in the spot.

And maybe you could add calloc(), though it's the same as malloc().
  • 0

#18 Guest

Guest

    CC Devotee

  • Expert Member
  • PipPipPipPipPipPip
  • 914 posts
  • Location:USA
  • Programming Language:C, Java, Python, Bash, Others
  • Learning:Assembly, Scheme

Posted 15 November 2009 - 08:02 AM

For some reason, I was probably thinking you had to return values at the end of the program. It is changed now.
  • 0
Root Beer == System Administrator's Beer
Download the new operating system programming kit! (some assembly required)

#19 n00py

n00py

    CC Lurker

  • Just Joined
  • Pip
  • 4 posts

Posted 30 January 2010 - 04:32 AM

You can define a pointer like so

No, that is an example of a declaration for a pointer variable. The definition of pointer is not "int *array;".

The pointer points to a random location at first

A pointer does always points to something (or has the value NULL).

According to the standard, a pointer variable contains an indeterminate value before it is initialised, and after free() is called with it's pointer value as an argument. Your debugger might set it to 0xbadc0de, for example. Using an indeterminate value such as this in any way (including a pointer comparison) is enough to invoke undefined behaviour according to the standard.

malloc() returns a void pointer and takes an argument of how many bytes to give to the pointer.

As previously stated, malloc accepts an argument that shall be the size of the allocation that the returned void pointer points to, providing the allocation is successful. malloc() does not "take an argument of how many bytes to give the pointer". The size in bytes of a void * pointer is constant when considering a specific implementation.

Using malloc like the above is very similar to doing this

I disagree. int array[2]; This is an example of using automemory. Automemory is valid only for it's scope. The memory allocated and pointed to by the return value of malloc() is valid up until it is deallocated using free().

Now I will show you how to use realloc().

realloc() may lead to code which leaves stale pointers. Using those stale pointers (even in a simple pointer comparison) invokes undefined behaviour according to the C standard.

You use realloc after you have used malloc to give the array more or less memory.

malloc() and realloc() are not operations that result in or operate on arrays. Arrays decay to pointers during runtime. Calling realloc() on an array would invoke undefined behaviour, and malloc()/realloc() return pointers that point to an allocated sequence of bytes. Here's an example that displays an obvious difference between a pointer and an array:
int array[100];
int *pointer = malloc(100);
printf("sizeof(array) = %zu\n", sizeof(array));
printf("sizeof(pointer) = %zu\n", sizeof(pointer));

When you done using a pointer, you can free the memory

You can only free() pointers that were specifically returned by malloc() or realloc(). free()ing any pointer which was not returned by malloc() or realloc() invokes undefined behaviour. Furthermore, when you are done with a pointer that is returned by malloc() or realloc(), you must deallocate it by calling free() with the pointer as it's argument in order to avoid memory leaks.

for (i--;i>=0;i--)
putchar(data[i]);

This is an example of invoking undefined behaviour.

Edited by n00py, 30 January 2010 - 05:02 PM.

  • 0

#20 Guest

Guest

    CC Devotee

  • Expert Member
  • PipPipPipPipPipPip
  • 914 posts
  • Location:USA
  • Programming Language:C, Java, Python, Bash, Others
  • Learning:Assembly, Scheme

Posted 31 January 2010 - 12:00 PM

No, that is an example of a declaration for a pointer variable. The definition of pointer is not "int *array;".

That's what I meant, I'll change it. ;)

According to the standard, a pointer variable contains an indeterminate value before it is initialised, and after free() is called with it's pointer value as an argument. Your debugger might set it to 0xbadc0de, for example. Using an indeterminate value such as this in any way (including a pointer comparison) is enough to invoke undefined behaviour according to the standard.

That's why I said the location is random. You don't know where it points to unless you initialize it.

As previously stated, malloc accepts an argument that shall be the size of the allocation that the returned void pointer points to, providing the allocation is successful. malloc() does not "take an argument of how many bytes to give the pointer". The size in bytes of a void * pointer is constant when considering a specific implementation.

The wording is a little weird there. I'll make it more clear.

I disagree. int array[2]; This is an example of using automemory. Automemory is valid only for it's scope. The memory allocated and pointed to by the return value of malloc() is valid up until it is deallocated using free().

I said it's similar, not exactly the same.

realloc() may lead to code which leaves stale pointers. Using those stale pointers (even in a simple pointer comparison) invokes undefined behaviour according to the C standard.

I don't know what a stale pointer is.

malloc() and realloc() are not operations that result in or operate on arrays. Arrays decay to pointers during runtime. Calling realloc() on an array would invoke undefined behaviour, and malloc()/realloc() return pointers that point to an allocated sequence of bytes. Here's an example that displays an obvious difference between a pointer and an array:

int array[100];
int *pointer = malloc(100);
printf("sizeof(array) = %zu\n", sizeof(array));
printf("sizeof(pointer) = %zu\n", sizeof(pointer));

Just problems with the wording I can easily fix.

You can only free() pointers that were specifically returned by malloc() or realloc(). free()ing any pointer which was not returned by malloc() or realloc() invokes undefined behaviour. Furthermore, when you are done with a pointer that is returned by malloc() or realloc(), you must deallocate it by calling free() with the pointer as it's argument in order to avoid memory leaks.

I'm aware of this, again it's something I should probably have clarified.

This is an example of invoking undefined behaviour.

How? I already know variable i is the index at the end of the allocated memory, and I'm just going backwards until i is less than zero.
  • 0
Root Beer == System Administrator's Beer
Download the new operating system programming kit! (some assembly required)

#21 Moudi

Moudi

    CC Addict

  • Just Joined
  • PipPipPipPipPip
  • 131 posts

Posted 08 March 2010 - 02:11 AM

Accually i have read this tutorial over 30 times, And finally, now i get realloc :P
  • 0

#22 Guest

Guest

    CC Devotee

  • Expert Member
  • PipPipPipPipPipPip
  • 914 posts
  • Location:USA
  • Programming Language:C, Java, Python, Bash, Others
  • Learning:Assembly, Scheme

Posted 08 March 2010 - 08:48 PM

If you needed help understanding it I probably could have helped you :P
It's good that you figured it out though.
  • 0
Root Beer == System Administrator's Beer
Download the new operating system programming kit! (some assembly required)

#23 dcs

dcs

    CC Devotee

  • Just Joined
  • PipPipPipPipPipPip
  • 730 posts

Posted 09 March 2010 - 03:25 PM

Accually i have read this tutorial over 30 times, And finally, now i get realloc :P

After this epiphany, do you have any descriptions that might be more "newb-accessible"? That is, something that might help the next guy "get it" in fewer rereads? [/curious]
  • 0

#24 n00py

n00py

    CC Lurker

  • Just Joined
  • Pip
  • 4 posts

Posted 10 March 2010 - 04:19 AM

First, I will show you how to allocate memory for a pointer.

Allocation and deallocation of memory to store the pointer value is automatic, because it's automatic memory. If a pointer is assigned to the return value of malloc(x), the pointer value is stored in automatic memory, but the memory that the pointer points to is dynamic. You've written a comment in your code later on that says something like "free the pointer"..........

int *ptr;

If this example follows on to the next one, then I'd suggest that the identifier used should be "ptr", in order to avoid confusion.

pointer=malloc(2*sizeof(int));


free(array);

There is no variable declaration for "array". I'm assuming you meant to carry on from the previous examples, which means "array" should in fact be "pointer". When using realloc, it's a common practise to set "pointer" to NULL after free()ing it, so that subsequent calls to realloc don't invoke undefined behaviour (by trying to use a pointer that has been free()d).

Aside from that, looks much better. I like how K&R's "The C Programming Language" worded it, however. That worked well for me ;) In regards to dcs' request, I believe it's necessary to explain pointers before dealing with malloc. Here's an extraction I've taken from K&R 2nd edition (page 93):
"Let us begin with a simplified picture of how memory is organized. A typical machine has an array of consecutively numbered or addressed memory cells that may be manipulated individually or in contiguous groups. One common situation is that any byte can be a char, ..." (in fact the C99 standard requires that the words "byte" and "char" be synonymous - 1 char is always 1 byte) "... a pair of one-byte cells can be treated as a short integer, and four adjacent bytes form a long. A pointer is a group of cells (often two or four) that can hold an address. ..." (it is worth noting the emphasis on the word common because a short integer isn't required to be 2 bytes, a long isn't required to be 4 bytes and a pointer ... well you get the picture) "... So if c is a char and p is a pointer that points into it, we could represent the situation in this way:"

...+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+...
   | p | p | p | p |   |   |   |   | c |   |   |   |   |   |   |   |
...+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+...

           |_________________________^
(ok, so my diagram is pathetic... get the book!)

"The unary operator & gives the address of an object, so the statement p = &c; assigns the address of c to the variable p, and p is said to point to c. ..."
"The unary operator * ... accesses the object the pointer points to. ..." (Given the statement p = &c; the variable c could be assigned using the pointer p like: *p = x;. or retrieved using the pointer p like: d = *p;)

The book then goes into detail regarding pointer arithmetic (which is good fun), but it is necessary to know that a pointer to foo type is different to an array of foo type. In summary, the differences are:

  • Pointer variables store pointer values. According to K&R: A pointer is a group of cells (often two or four) that can hold an address..
  • The sizeof() operator used on an array will result in the number of bytes that the items within the array occupy. The sizeof() operator used on a pointer will result in the number of bytes that the pointer value occupies. On a side note, in many cases a pointer to foo is not required to be the same size as a pointer to bar. See the C99 standard draft for more information.
  • Arrays are automatically managed. They are destroyed when their scope runs out. Pointer variables store pointer values. Pointer values point to objects. Arrays degrade to pointer values during runtime. A pointer variable is automatically managed, though the memory that a pointer value points to isn't (unless the pointer value points to automatic memory).

Back to K&R, page 252:
void *malloc(size_t size);
malloc returns a pointer to space for an object of size bytes, or NULL if the request cannot be satisfied. The space is uninitialized.


The K&R description of realloc is not so great, so I've decided to use the opengroup realloc page as a reference for realloc. At this moment in time (which is important because the proposed new C1X standard may change some things), the page states:
void *realloc(void *ptr, size_t size);
The realloc() function shall change the size of the memory object pointed to by ptr to the size specified by size. The contents of the object shall remain unchanged up to the lesser of the new and old sizes. If the new size of the memory object would require movement of the object, the space for the previous instantiation of the object is freed. If the new size is larger, the contents of the newly allocated portion of the object are unspecified. If size is 0 and ptr is not a null pointer, the object pointed to is freed. If the space cannot be allocated, the object shall remain unchanged. (and NULL will be returned)

If ptr is a null pointer, realloc() shall be equivalent to malloc() for the specified size.
If ptr does not match a pointer returned earlier by calloc(), malloc(), or realloc() or if the space has previously been deallocated by a call to free() or realloc(), the behavior is undefined.

Edited by n00py, 10 March 2010 - 09:19 PM.

  • 0





Also tagged with one or more of these keywords: dynamic array, realloc, malloc, array