Why allocating a 0 size char block works in this case? But if I write char *string = NULL; it won't work.
I'm using Visual Studio.
int main()
{
char *string = (char *)malloc(0);
string[0] = 'a';
string[1] = 'b';
string[2] = 'c';
string[3] = 'd';
string[4] = '\0';
printf("%s\n",string);
return 0;
}
First let me state, as per the man page of malloc()
The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().
a call like malloc(0) is valid itself, but then, we need to check the validity of the returned pointer. It can either
Return NULL
Return a pointer which can be passed to free().
but anyways, dereferencing that pointer is not allowed. It will cause out-of-bound memory access and cause undefined behaviour.
That said, two important things to mention,
Please see why not to cast the return value of malloc() and family in C.
Please check the return value of malloc() before using the returned pointer.
So, to answer your question,
Difference between initializing a string with (char *)malloc(0) and NULL
Do not use malloc(0) in this case, as a NULL check on the pointer may fail, giving the wrong impression of a valid allocation of the memory to the pointer. Always use NULL for initialization.
The above code invokes undefined behavior. You have allocated insufficient memory and you are accessing invalid addresses.
According to the specifications, malloc(0) will return either "a null pointer or a unique pointer that can be successfully passed to free()".
malloc definition:
Allocates a block of size bytes of memory, returning a pointer to the
beginning of the block.
The content of the newly allocated block of memory is not initialized,
remaining with indeterminate values.
If size is zero, the return value depends on the particular library
implementation (it may or may not be a null pointer), but the returned
pointer shall not be dereferenced.
Taken from here and found this related question.
Related
I have allocated memory for a char pointer in this code and I wanted check does it points anything:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char *p = (char*) malloc(sizeof(char)*10);
if(*p == 0)
printf("The pointer points nothing !\n");
}
And I checked that if it doesn't point anything. Also I print of pointer's length and it prints "3" although it prints nothing. What is reason of this and how can I check if it points nothing ?
You need to modify the check to check against the returned pointer, not the content. Something like
if( p == NULL) {
fprintf(stderr, "The pointer points nothing !\n");
return 1;
}
should do. Quoting the standard regarding the return values:
The malloc function returns either a null pointer or a pointer to the allocated space.
The null pointer is returned in case of a failure, otherwise the pointer returned should be non-equal to a null pointer.
That said,
The initial content of the pointed memory is indeterminate, do not attempt to verify it. Quoting from the standard,
The malloc function allocates space for an object whose size is specified by size and
whose value is indeterminate.
That goes for your other question regarding "checking the length" of the pointer - it's pointless. Unless you have stored (write) some value into it - there's no point trying to measure the initial content, as it is indeterminate. You may eventually run into undefined behavior.
The cast for the returned pointer by malloc() and family is superfluous. It can be totally avoided in C.
sizeof(char) is guaranteed to be 1, in C. Thus, using sizeof(char) as a multiplier, is again not needed, per se.
I'm having some trouble reading a like from user using malloc and getchar. I get the result, however, I get memory leaks using valgrind. I am pretty clueless in this and have asked my classmates and mentors, but none seem to find out why.
char *ReadLineFile(FILE *infile){
int i=0;
char c;
char *newStringLine;
newStringLine = (char *) malloc(sizeof(char));
while( (c = fgetc(infile)) != '\n' ){
newStringLine[i++] = c;
realloc(newStringLine, (sizeof(char) * (i+1)));
}
newStringLine[i] = '\0';
return newStringLine;
}
Valgrind gives me several errors, including Invalid write/read of 1, and invalid realloc.
Your usage of realloc() is erroneous.
realloc(), if successful, frees the passed pointer and returns a new pointer with the allocated memory. You need to
catch the return value of realloc() in a temporary pointer,
check against NULL to ensure success and then
If returned pointer is not NULL, i.e., reallocation is successful, use the new pointer.
If the returned pointer is NULL, make some decisions and you can keep using the old pointer (passed as argument).
Related, quoting C11, chapter §7.22.3.5
The realloc function deallocates the old object pointed to by ptr and returns a
pointer to a new object that has the size specified by size. [....]
and,
[...] If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
Otherwise, in case, realloc() is successful, you are (most probably) trying to use an already free-d memory, which , of course, causes undefined behavior.
Uh-oh, and did I mention, please see this discussion on why not to cast the return value of malloc() and family in C?
In the following example, function func() returning an address of a local pointer variable to main() function. It's working fine in GCC.
So, Is it well-defined behaviour?
#include <stdio.h>
#include <stdlib.h>
int *func(void);
int *func(void)
{
int *p;
p = malloc(sizeof *p);
*p = 10;
return p;
}
int main()
{
int *ptr = func();
printf("%d\n",*ptr);
return 0;
}
No, you do not return a pointer to (address of) a local variable. That would be doing something like
int i = 10;
return &i;
Instead you return a pointer to an object allocated on the heap.
You do have a memory leak though, since you don't free the memory anywhere. Calling free should be done by the code calling your function (unless it in turn return the pointer value, where the responsibility continues upt he call-chain).
Inside func(), p is a pointer to memory allocated by malloc() (or to potentially allocated memory, since malloc() can fail, returning a null pointer; this should be checked for). If successful, this memory allocation will persist until it is explicitly freed.
The value of p is returned to the calling function, main() in this case. p is either a pointer to a successful allocation, or is a null pointer, and the returned value (which is temporary, and not an lvalue) is then assigned to ptr. So, the allocated storage can be accessed through ptr, which is a copy of the value held by p before func() returned, though the lifetime of p itself has ended now that func() has returned.
Of course ptr should be freed when it is no longer needed to avoid memory leaks. And, there is potential undefined behavior here if malloc() fails, since then ptr is a null pointer.
This is perfectly valid.
What is not guaranteed is what will happen to the variables on the stack frame once a function returns and the stack frame shrinks.
What you are returning is an address to some malloced memory and not the address of a local variable (allocated on the stack). This is very similar to how strdup() works. Here's an implementation of strdup() taken from here.
char *
strdup(str)
const char *str;
{
size_t len;
char *copy;
len = strlen(str) + 1;
if (!(copy = malloc((u_int)len)))
return (NULL);
bcopy(str, copy, len);
return (copy);
}
One obvious downside of this (as mentioned by "Some programmer dude") is that the responsibility of freeing is passed on to the caller.
This is a valid and correct code, although bit confusing.
The func is allocating memory of size int. The allocation is done via de-referencing a pointer variable of type int.
Alter allocation the integer value of 10 is set in the memory. 10 should be set as integer (can be compiler dependent). But definitely will not be of greater than the size of integer so should be safe operation.
After that the pointer value is returned by the function.
In main() the returned pointer is set to another integer pointer. This points to the original memory allocated by malloc().
After that the de-referenced integer pointer is printed in the printf() statement. This will print the value of 10.
What is missing is the free() call, which is not the good behaviour in here.
This can be a good academic exercise for kids.
Is the behavior implementation defined? If NULL and size == 0 are passed to realloc():
int main(void)
{
int *ptr = NULL;
ptr = realloc(ptr, 0);
if(ptr == NULL)
{
printf("realloc fails.\n");
goto Exit;
}
printf("Happy Scenario.\n");
Exit:
printf("Inside goto.\n");
return 0;
}
The above code should print "realloc fails", right? But it is not? I've read somewhere that this call to realloc may return NULL also. When does that happen?
This behavior is implementation defined.
From the C standard:
Section 7.22.3.5 (realloc):
3 If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size. Otherwise, if ptr
does not match a pointer earlier returned by a memory management
function, or if the space has been deallocated by a call to
the free or realloc function, the behavior is undefined. If
memory for the new object cannot be allocated, the old object is
not deallocated and its value is unchanged.
So realloc(NULL, 0) is the same as malloc(0)
If we then look at section 7.22.3.4 (malloc):
2 The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.
3 The malloc function returns either a null pointer or a pointer to the allocated space.
The standard does not state what happens when 0 is passed in.
But if you look at the Linux man page:
The malloc() function allocates size bytes and returns a pointer to
the allocated memory. The memory is not initialized. If size is 0,
then malloc() returns either NULL, or a unique pointer value that can
later be successfully passed to free().
It explicitly states that the returned value can be freed but is not necessarily NULL.
In contrast, MSDN says:
If size is 0, malloc allocates a zero-length item in the heap and
returns a valid pointer to that item. Always check the return from
malloc, even if the amount of memory requested is small.
So for MSVC, you won't get a NULL pointer.
realloc(3) doc:
If ptr is NULL, then the call is equivalent to malloc(size), for all values of size
malloc(3) doc:
If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be success‐fully passed to free().
So yes, it is implementation defined, you'll either get null or a pointer you can free.
The call
realloc(NULL, size);
is equivalent to
malloc(size);
And what malloc() does when asked to allocate 0 bytes is a bit unclear, the standard doesn't say. I think it's implementation-defined. It basically "doesn't matter"; either it returns NULL, or it returns a pointer where you can legally access zero bytes, those are pretty much alike. Both can be passed to free().
In C, must I always initialize my last node pointing to NULL? I generally see this happening in tutorials and in books. But to my understanding, an unitialized pointer holds the same address as a NULL pointer. So why initialize?
But to my understanding, an uninitialized pointer holds the same address as a NULL pointer
It might, by (bad) luck.
In any case reading out an uninitialised pointer invokes undefined behaviour. Whether this would lead to a crash (or any other "strange" behaviour) sooner or later is unknown, as by the nature of undefined behaviour.
However depending on how the memory the pointer variable "lives" in is allocated, the memory might come as "already" initialised, if allocating
it statically or
via calling calloc()
Both methods allocate memory and 0 it out in advance. Which, for most recent systems, is sufficient to have a pointer variable (living inside this memory) carrying the value of NULL.
But please note that there still might be implementations around that use a different bit pattern for NULL than just 0-bits. So to stay 100% portable it is good advice to always initialise with NULL explicitly and not rely on implicitly cleared out memory. And btw, this also helps the potential reader of your sources.
When you create a pointer without initializing it, let's say
char *ptr;
The memory points to some bytes (depending on your pointer type).
Those bytes, may be anything. Like some previous initialized unfreed pointer, or, to some garbage.
Which is not the same as a NULL pointer.
To avoid that, you should take the habit of initializing every of your pointers (except for globals and statics which are initialized to 0) and, add a NULL every-time you work with arrays or anything containing multi-elements.
Let's say that in this case, NULL is the '\0' of the array/list.
For example, if you want to create an array containing a few char *, do it this way :
void function()
{
char *array[4];
array[0] = strdup("Jason");
array[1] = strdup("Mike");
array[2] = strdup("Nicole");
array[3] = NULL;
}
It helps you not to go further than the memory you previously allocated for this pointer, avoiding memory fails, and segmentation faults. In case you're using a counter to get through every case of this array.
Otherwise, don't use NULL everywhere, if you allocated a string, don't fill it with NULL after on.
int main()
{
char *ptr;
if ((ptr = malloc(sizeof(char) * 42)) == NULL)
return (-1);
ptr = NULL;
return (0);
}
This won't work because you're sending NULL into the bytes you cleaned straight before.
If you want to properly use a pointer and clean it before using it, you can use memset. Which will send a x amount of the same byte into the pointer, cleaning the garbage that might be in it by the bytes you passed into memset parameters.
You might think that null pointer is the pointer that is uninitialized, but it's wrong. Null pointer is a special pointer which doesn't points to anywhere.
// To declare a null pointer.
int *ptr=NULL;
if(ptr==NULL) //..do something..
Functions like malloc() and getchar() returns null pointer in case they are unable to perforn their task or complete the task.
An uninitialized pointer can hold any garbage value.
an uninitialized local variable's value is undefined. while the static or global will grantee to be 0.
it is a good practice to initialize all variable you defined, otherwise, it may result very very trick bug.
Contrary to your understanding, the content of an uninitialized pointer is undefined. Only if the object is statically allocated is it guaranteed to be zero initialised.