Is it common practice to memset reallocated memory to 0? - c

In a C book I found in an example for implementing a dynamically resizing array this code (simplified):
void *contents = realloc(array->contents, array->max * sizeof(void *));
array->contents = contents;
memset(array->contents + old_max, 0, array->expand_rate + 1);
Source: Learn C The Hard Way – Chapter 34
I was a bit surprised what memset is supposed to achieve here, but then I understood it's used in order to "zero out" the reallocated memory.
I googled in order to find out, if this is what I'm supposed to do after a realloc and found a stackoverflow answer regarding this:
There is probably no need to do the memset […]
But, even if you wanted to "zero it out so everything is nice", or really need the new pointers to be NULL: the C standard doesn't guarantee that all-bits-zero is the null pointer constant (i.e., NULL), so memset() isn't the right solution anyway.
Source: How to zero out new memory after realloc
The suggested solution instead of memset is then to use a for loop in order to set the memory to NULL.
So my question is, as memset does not necessarily mean setting values to NULL and the for loop solution seems a bit tedious – is it really needed to set the newly allocated memory?

So my question is, as memset does not necessarily mean setting values
to NULL and the for loop solution seems a bit tedious – is it really
needed to set the newly allocated memory?
realloc doesn't initialize values of the newly allocated memory segment.
So it is needed to initialize the memory if you are planning to read values of that (uninitialized) memory. Because reading values from that uninitialized memory will trigger undefined behaviour.
By the way, safe way to use realloc (since it can fail) is:
// Since using realloc with size of 0 is tricky and useless probably
// we use below check (from discussion with #chux)
if (new_size == 0)
dosmth();
else
{
new_p = realloc(p, new_size);
if (new_p == NULL)
{
// ...handle error
}else
{
p = new_p;
}
}

Setting a void * to 0 is a value that will compare equal to NULL. Likely memset(ptr, 0, size) is OK - but need to see more code for certainty.
OTOH: is the code correct? Maybe should be
// memset(array->contents + old_max, 0, array->expand_rate + 1);
memset(array->contents + old_max, 0, sizeof(void *) * (array->expand_rate + 1) );

This is wrong:
But, even if you wanted to "zero it out so everything is nice", or
really need the new pointers to be NULL: the C standard doesn't
guarantee that all-bits-zero is the null pointer constant (i.e.,
NULL), so memset() isn't the right solution anyway.
The C standard does in fact guarantee exactly that.
Per section 6.3.2.3 of the C standard:
An integer constant expression with the value 0, or such an expression
cast to type void *, is called a null pointer constant. If a null
pointer constant is converted to a pointer type, the resulting
pointer, called a null pointer, is guaranteed to compare unequal to
a pointer to any object or function.
Conversion of a null pointer to another pointer type yields a null
pointer of that type. Any two null pointers shall compare equal.
Note that a pointer with a value of zero is a null pointer. That doesn't mean NULL itself has to be zero. But also note that "any two null pointers shall compare equal". So any null pointer is equal to the NULL value.
Since memset() takes as its second argument an integer value, passing a zero integer value to memset() will produce null pointers. Because the value passed to memset() is "[a]n integer constant expression with the value 0", per 6.3.2.3.

Related

memory allocated by NULL pointers

Does NULL pointer take any memory?
If it takes memory,then how much memory is consumed by it and what is the significant use of NULL pointer if it takes memory?
A pointer value (NULL or not) requires some amount of space to store and represent (4 to 8 bytes on most modern desktop systems, but could be some oddball size depending on the architecture).
The pointer value NULL represents a well-defined "nowhere"; it's an invalid pointer value guaranteed to compare unequal to the address of any object or function in memory. The macro NULL is set to the null pointer constant, which is a zero-valued integer expression (either a naked 0, or (void *) 0, or some other expression that evaluates to 0).
After the code has been compiled, the null pointer constant will be replaced with the appropriate null pointer value for that particular platform (which may be 0x00000000, or 0xFFFFFFFF, or 0xDEADBEEF, or some other value).
Any pointer value, including NULL, takes a small, system-dependent amount of space to express or store.
That's an altogether separate consideration from any space that the pointed-to object, if any, may require. A NULL pointer is guaranteed to not point to any object, but a non-NULL pointer is not guaranteed to point to an object. On the other hand, there may be more than one pointer to the same object.
Where a NULL pointer is intentionally used, it is typically used to explicitly express an invalid pointer, since you cannot tell from any other pointer value whether that pointer is valid. This can be useful, for example, as a sentinel value marking the end of an unknown-length array of pointers, or as a function return value indicating failure. The canonical example of the latter might be malloc(), which returns NULL if it fails to allocate the requested space.
A NULL pointer doesn't allocate anything. If you have a definition like this:
int *x = NULL;
That means the variable x, which points to an int, doesn't point to anything. You can then check if (x == NULL) to see if it points to valid memory.

Dynamic memory allocation questions with realloc and calloc

See the following function:
int go(void) {
int *p, *q;
p = calloc(10,sizeof(int));
q = realloc(p, 20 * sizeof(int));
<<X>>
}
Assuming that both memory allocation function calls are successful, which of the following statements are true at the point marker <<X>>.
The values of p and q are the same.
p points to 10 integers each with the value of 0.
q points to at least 80 bytes of memory.
This question is in my C test paper. Except for (2) which is obviously true. I'm quite confused about (1) and (3). Can anybody explain me this?
Check out the documentation. Specifically (emphasis added):
RETURN VALUE
Upon successful completion with a size not equal to 0, realloc()
returns a pointer to the (possibly moved) allocated space. If size is
0, either a null pointer or a unique pointer that can be successfully
passed to free() is returned. If there is not enough available memory,
realloc() returns a null pointer and sets errno to [ENOMEM].
So, the p and q may be the same (if realloc is able to resize the existing block of memory), but it's not guaranteed (and so you shouldn't rely on it).
According to the C standard, an int must be at least 16 bits (2 bytes), so sizeof(int) is at least 40, so (3) is not necessarily true.
As Brendan said, (1) is not necessarily true (and probably not true).
In C, generally an "int" is 4 bytes, so (3) should be true. It is true on all systems that I know of, although I'm not positive that the C standard says that an "int" must be four bytes long.
1) both p and q are pointers. Look up documentation on what realloc does for the answer. 3) That statement is ambiguous. In C, the value of pointers are typically scalar addresses to a byte location. The size of the memory block allocated is unknown. The type of the pointer is used to determine the size of a stride when doing pointer arithmetic, but if you allocated a buffer of a multiple size of some type, that is still unknown from the variable itself.
Chech these link.These says that 1 may be true or false its like can't say http://www.thinkage.ca/english/gcos/expl/c/lib/reallo.html
Hope these information helps you as many people already explained about 3rd case
1 is true or false
because q points to the reallocated memory. This may be the same as "p" if the old block of memory could be grown (or shrunk) to the new size; otherwise, it will be a different block. The space begins at an alignment boundary that is suitable for storing objects of any data type. If memory cannot be acquired or if an argument is improperly specified, the NULL pointer is returned.
The amount of memory pointed to by q depends on the size of the int type, which might not be four bytes. Statement one is also not necessarily true. From the realloc(3) man page on my system:
If there is not enough room to
enlarge the memory allocation pointed to by ptr, realloc() creates a new
allocation, copies as much of the old data pointed to by ptr as will fit
to the new allocation, frees the old allocation, and returns a pointer to
the allocated memory.
As this is an exam question, we have to refer to the specification. All three are to be considered false.
realloc can return a pointer that is different to p.
realloc can will free the memory pointed to by p if the newly allocated space is in a different location. This means that p may still point to ten zeros, but this is not what the specification says.
As explained well in other answers, we don't know the size of an int (that is why we use sizeof(int)).

Need assistance in understanding this code using malloc and pointers

Here is a little snippet of code from Wikipedia's article on malloc():
int *ptr;
ptr = malloc(10 * sizeof (*ptr)); // Without a cast
ptr = (int*)malloc(10 * sizeof (int)); // With a cast
I was wondering if someone could help me understand what is going on here. So, from what I know, it seems like this is what's happening:
1) initialize an integer pointer that points to NULL. It is a pointer so its size is 4-bytes. Dereferencing this pointer will return the value NULL.
2) Since C allows for this type of automatic casting, it is safe not to include a cast-to-int-pointer. I am having trouble deciphering what exactly is being fed into the malloc function though (and why). It seems like we are getting the size of the dereferenced value of ptr. But isn't this NULL? So the size of NULL is 0, right? And why are we multiplying by 10??
3) The last line is just the same thing as above, except that a cast is explicitly declared. (cast from void pointer to int pointer).
I'm assuming we're talking about C here. The answer is different for C++.
1) is entirely off. ptr is a pointer to an int, that's all. It's uninitialized, so it has no deterministic value. Dereferencing it is undefined behaviour -- you will most certainly not get 0 out! The pointer also will most likely not point to 0. The size of ptr is sizeof(ptr), or sizeof(int*); nothing else. (At best you know that this is no larger than sizeof(void*).)
2/3) In C, never cast the result of malloc: int * p = malloc(sizeof(int) * 10);. The code allocates enough memory for 10 integers, i.e. 10 times the size of a single integer; the return value of the call is a pointer to that memory.
The first line declares a pointer to an integer, but doesn't initialize it -- so it points at some random piece of memory, probably invalid. The size of ptr is whatever size pointers to int are, likely either 4 or 8 bytes. The size of what it points at, which you'd get by dereferencing it when it points somewhere valid, is whatever size an int has.
The second line allocates enough memory for 10 ints from the heap, then assigns it to ptr. No cast is used, but the void * returned by malloc() is automatically converted to whatever type of pointer is needed when assigned. The sizeof (*ptr) gives the size of the dereferenced ptr, i.e. the size of what ptr points to (an int). For sizeof, it doesn't matter whether ptr actually points to a valid memory, just what the type would be.
The third line is just like the second, but with two changes: It explicitly casts the void * return from malloc() to an int *, to match the type of ptr; and it uses sizeof with the type name int rather than an expression of that type, like *ptr. The explicit cast is not necessary, and some people strongly oppose its use, but in the end it comes down to preference.
After either of the malloc()s ptr should point to a valid location on the heap and can be dereferenced safely, as long as malloc was successful.
For line 2 malloc() is allocating enough memory to hold 10 pointers.
malloc() is a general purpose function void so it must be cast to whatever type you actually want to use, in the above example pointer to int.

Pointer pointing to an empty array

I have a pointer that is pointing to the start of an array, but I need to check that it is unallocated. I thought of dereferencing the pointer and checking if NULL but that leads to a type error. Can anyone see what I'm doing wrong?
int mydispose(int *array){
int i = 0;
if(*array == NULL){
return 1;
}
return ;
}
EDIT: Sorry if I was unclear: I have a pointer that points to the start of an array, but I wish to check whether the array is empty.
*array == NULL is wrong. You are dereferencing the pointer first (which could lead to a segfault if the pointer really is null) and then comparing its int value to a pointer value. Moreover, your compiler will perfectly accept that erroneous expression if NULL is defined as just 0 and not (void *) 0.
You should be checking array == NULL to see if the passed pointer refers to anything, and then dereference it only in case it's not NULL.
Be aware, however, that dereferencing a non-null pointer isn't guaranteed to be a safe operation either. If the pointer contains a garbage value because it was allocated on the stack and not initialized, or if it refers to a deallocated region of memory, nasty bugs can happen.
You want if (array == NULL) -- but unless you first initialize array to NULL, it won't do any good either. I think you'd be better off backing up and telling us a bit more about what you're trying to accomplish, and trying to get help trying to accomplish your overall goal.
The only safe way to determine the allocation status of *array is to:
Make sure *array is set to NULL is not allocated. int *array = NULL;
Check if the array is NULL: if (array == NULL) return -1;
You can't reliably check if some memory location is allocated. *array is not a valid code, because it's the same as array[0], but array[0] is not allocated. Non-allocated memory location can contain any value.
The only option is to ensure that you get the information whether the array is allocated alongside with your array. A popular option is representing unallocated array as NULL, but you may choose other option as well.
By the way, there is a difference between an empty array (that is, array of size 0), and array which is not allocated at all. The first option occurs when you use malloc(0), the second when your pointer is not initialized at all. For malloc(0) it's allowed to return NULL, but it's allowed to return a non-NULL pointer (which you however can't dereference) as well. Both ways are valid according to the standard.
The immediate problem with your code is that you dereferencing array before comparing it to NULL. The type of the expression *array is int, not int *. Leave off the dereference operator and the types will match:
if (array == NULL) {...}
Note that an uninitialized pointer is only guaranteed to contain NULL if it was declared with static extent (i.e. it was either declared at file scope or with the static keyword in front of it). Similarly, calling free on a pointer won't set that pointer value to NULL; it will contain the same pointer value as before, but it will now be invalid.
You must use it like this:
if(array == NULL) ...

What does malloc(0) return? [duplicate]

This question already has answers here:
What's the point of malloc(0)?
(17 answers)
Closed 8 years ago.
What does malloc(0) return?
Would the answer be same for realloc(malloc(0),0)?
#include<stdio.h>
#include<malloc.h>
int main()
{
printf("%p\n", malloc(0));
printf("%p\n", realloc(malloc(0), 0));
return 0;
}
Output from Linux GCC:
manav#manav-workstation:~$ gcc -Wall mal.c
manav#manav-workstation:~$ ./a.out
0x9363008
(nil)
manav#manav-workstation:~$
The output keep changing everytime for malloc(0). Is this a standard answer? And why would anyone be interested in getting such a pointer, other than academic research?
EDIT:
If malloc(0) returns dummy pointer, then how does following works:
int main()
{
void *ptr = malloc(0);
printf("%p\n", realloc(ptr, 1024));
return 0;
}
EDIT:
The following code outputs "possible" for every iteration. Why should it not fail ?
#include<stdio.h>
#include<malloc.h>
int main()
{
int i;
void *ptr;
printf("Testing using BRUTE FORCE\n");
for (i=0; i<65000; i++)
{
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
printf("Iteration %d: possible\n", i);
else
{
printf("Failed for iteration %d\n", i);
break;
}
}
return 0;
}
Others have answered how malloc(0) works. I will answer one of the questions that you asked that hasn't been answered yet (I think). The question is about realloc(malloc(0), 0):
What does malloc(0) return? Would the answer be same for realloc(malloc(0),0)?
The standard says this about realloc(ptr, size):
if ptr is NULL, it behaves like malloc(size),
otherwise (ptr is not NULL), it deallocates the old object pointer to by ptr and returns a pointer to a new allocated buffer. But if size is 0, C89 says that the effect is equivalent to free(ptr). Interestingly, I can't find that statement in C99 draft (n1256 or n1336). In C89, the only sensible value to return in that case would be NULL.
So, there are two cases:
malloc(0) returns NULL on an implementation. Then your realloc() call is equivalent to realloc(NULL, 0). That is equivalent to malloc(0) from above (and that is NULL in this case).
malloc(0) returns non-NULL. Then, the call is equivalent to free(malloc(0)). In this case, malloc(0) and realloc(malloc(0), 0) are not equivalent.
Note that there is an interesting case here: in the second case, when malloc(0) returns non-NULL on success, it may still return NULL to indicate failure. This will result in a call like: realloc(NULL, 0), which would be equivalent to malloc(0), which may or may not return NULL.
I am not sure if the omission in C99 is an oversight or if it means that in C99, realloc(ptr, 0) for non-NULL ptr is not equivalent to free(ptr). I just tried this with gcc -std=c99, and the above is equivalent to free(ptr).
Edit: I think I understand what your confusion is:
Let's look at a snippet from your example code:
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
The above is not the same as malloc(0) == realloc(malloc(0), 1024). In the second, the malloc() call is made twice, whereas in the first, you're passing a previously allocated pointer to realloc().
Let's analyze the first code first. Assuming malloc(0) doesn't return NULL on success, ptr has a valid value. When you do realloc(ptr, 1024), realloc() basically gives you a new buffer that has the size 1024, and the ptr becomes invalid. A conforming implementation may return the same address as the one already in ptr. So, your if condition may return true. (Note, however, looking at the value of ptr after realloc(ptr, 1024) may be undefined behavior.)
Now the question you ask: malloc(0) == realloc(malloc(0), 1024). In this case, let's assume that both the malloc(0) on the LHS and RHS returns non-NULL. Then, they are guaranteed to be different. Also, the return value from malloc() on the LHS hasn't been free()d yet, so any other malloc(), calloc(), or realloc() may not return that value. This means that if you wrote your condition as:
if (malloc(0) == realloc(malloc(0), 1024)
puts("possible");
you won't see possible on the output (unless both malloc() and realloc() fail and return NULL).
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
void *p1;
void *p2;
p1 = malloc(0);
p2 = realloc(p1, 1024);
if (p1 == p2)
puts("possible, OK");
/* Ignore the memory leaks */
if (malloc(0) == realloc(malloc(0), 1024))
puts("shouldn't happen, something is wrong");
return 0;
}
On OS X, my code didn't output anything when I ran it. On Linux, it prints possible, OK.
malloc(0) is Implementation Defined as far as C99 is concerned.
From C99 [Section 7.20.3]
The order and contiguity of storage allocated by successive calls to the calloc,
malloc, and realloc functions is unspecified. The pointer returned if the allocation
succeeds is suitably aligned so that it may be assigned to a pointer to any type of object
and then used to access such an object or an array of such objects in the space allocated
(until the space is explicitly deallocated). The lifetime of an allocated object extends
from the allocation until the deallocation. Each such allocation shall yield a pointer to an
object disjoint from any other object. The pointer returned points to the start (lowest byte
address) of the allocated space. If the space cannot be allocated, a null pointer is
returned. If the size of the space requested is zero, the behavior is implementation-
defined: either a null pointer is returned, or the behavior is as if the size were some
nonzero value, except that the returned pointer shall not be used to access an object.
In C89, malloc(0) is implementation dependent - I don't know if C99 has fixed this or not. In C++, using:
char * p = new char[0];
is well defined - you get a valid, non-null pointer. Of course, you can't use the pointer to access what it points to without invoking undefined behaviour.
As to why this exists, it is convenient for some algorithms, and means you don't need to litter your code with tests for zero values.
C99 standard
If the space cannot be allocated, a
nullpointer is returned. If the size
of the space requested is zero, the
behavior is implementation-defined:
either a null pointer is returned, or
the behavior is as if the size were
some nonzero value, except that the
returned pointer shall not be used to
access an object.
The comp.lang.c FAQ has the following to say:
The ANSI/ISO Standard says that it may
do either; the behavior is
implementation-defined (see question
11.33). Portable code must either take care not to call malloc(0), or be
prepared for the possibility of a null
return.
So, it's probably best to avoid using malloc(0).
One point nobody cared to talk about yet, in your first program is that realloc with length 0 is the same thing as free.
from the Solaris man page:
The realloc() function changes the size of the block pointed
to by ptr to size bytes and returns a pointer to the (possibly moved) block. The contents will be unchanged up to the
lesser of the new and old sizes. If ptr is NULL, realloc()
behaves like malloc() for the specified size. If size is 0
and ptr is not a null pointer, the space pointed to is made
available for further allocation by the application, though
not returned to the system. Memory is returned to the system
only upon termination of the application.
If one doesn't know that it can be a source of bad surprise (happened to me).
See C99, section 7.20.3:
If the size of the space requested is
zero, the behavior is
implementationdefined: either a null
pointer is returned, or the behavior
is as if the size were some nonzero
value, except that the returned
pointer shall not be used to access an
object.
This is valid for all three allocation functions (ie calloc(), malloc() and realloc()).
I think it depends.
I checked the Visual Studio 2005 sources and saw this in the _heap_alloc function:
if (size == 0)
size = 1;
I think that in many cases you may want a valid pointer, even when asking for zero bytes.
This is because this consistent behavior makes it easier to check your pointers because: if you have a non-NULL pointer it's OK; if you have a NULL pointer you probably have a problem.
That's why I think that most implementations will return a valid pointer, even when asking for zero bytes.
If malloc(0) returns dummy pointer, then how does following works:
void *ptr = malloc(0);
printf("%p\n", realloc(ptr, 1024));
I don't know what you mean by "dummy pointer". If malloc(0) returns non-NULL, then ptr is a valid pointer to a memory block of size zero. The malloc implementation saves this information in an implementation-specific way. realloc knows the (implementation-specific) way to figure out that ptr points to a memory block of size zero.
(How malloc/realloc/free do this is implementation-specific. One possibility is to allocate 4 bytes more than requested and store the size just before the memory block. In that case, ((int *)ptr)[-1] would give the memory block size, which is 0. You should never do this from your code, it's only for use by realloc and free).

Resources