Need help in understanding malloc(0) for my example [duplicate] - c

This question already has answers here:
Undefined, unspecified and implementation-defined behavior
(9 answers)
What does malloc(0) return? [duplicate]
(9 answers)
Closed 6 years ago.
I am trying to understand inners of double pointer (which is pointer holding another pointer) to form an array of pointers. So, I am trying to run the following code by experimenting on malloc to debugging and see how it works. I am unable to understand what malloc(0) does in my case, but my code works by outputting "Hello World".
What is the diff between
pToCharsPointers = (char**) malloc(0);
and
pToCharsPointers = (char**) malloc(2 * sizeof(char*));
Please someone clarify what it is doing in my case.
#include <stdio.h>
char **pToCharsPointers;
int main(void)
{
pToCharsPointers = (char**) malloc(0);
char* pToChars = "Hello";
*pToCharsPointers = pToChars;
*(pToCharsPointers + 1)= "World";
printf("%s %s\n", *(pToCharsPointers + 0), *(pToCharsPointers + 1));
return 0;
}
Also, I would really appreciate if you anyone could explain how double pointers works with an example in memory for visualizing as I fail to see myself even though I tried to read about this in many places.
EDIT: Thanks everyone for sharing your answers, and it really helped to understand. I got a valid pointer with malloc(0) when I printed it, and can dereference it also without issues during multiple tries. Wanted to understand why its working. Seems like in my case undefined behavior was actually a expected one.

In your code
(char**) malloc(0);
is wrong for two reasons, like
Passing size as 0 is implementation defined behaviour and the returned pointer cannot be dereferenced. Quoting the manual page,
If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().
Please see this discussion on why not to cast the return value of malloc() and family in C..
Any code, attempting to use the returned pointer for a code like yours, will be essentially dereferencing invalid memory which invokes undefined behavior. So, the output/behaviour of your program can neither be predicted nor reasonified.
OTOH, a statement like
pToCharsPointers = malloc(2 * sizeof(char*));
is valid but you ought to check the validity of the returned pointer to ensure malloc() is success.

I will try to explain:
pToCharsPointers = (char**) malloc(0);
this line will bring to pToCharPointers a pointer that you can't use
but you can't know if an error will come. don't do that!
char* pToChars = "Hello";
*pToCharsPointers = pToChars;
this line will bring *pToCharsPointers to pToChar that pointing to the "Hello".
*(pToCharsPointers + 1)= "World";
this line will write in *(pToCharsPointers + 1), that you can't know to where it is pointing, "World". also, an option to an error but not for sure.
printf("%s %s\n", *(pToCharsPointers + 0), *(pToCharsPointers + 1));
this line will print "Hello Wolrd" if you didn't get any errors yet.

It simply asks to allocate zero bytes. It is up to the implementation of malloc if it should return a null pointer or not.
Even if it returns a non-null pointer, you can't dereference it since it will automatically be out of bounds. Dereferencing the returned pointer will lead to undefined behavior in both cases.
When you do malloc(2 * sizeof(char*)) you allocate enough space for two pointers to char.

You forgot to include <stdlib.h>. Calling malloc() without a proper definition has undefined behavior. Explicitly casting its return value hides the fact that the compiler may assume it returns an int value. This cast is necessary in C++, where calling a function without a prior definition is invalid, but it is counter-productive in C.
Regarding your question: allocating a block of size zero can have two possible outcomes, depending on the implementation of your C library:
malloc(0) can return NULL, and attempting to store values at this address has undefined behavior.
malloc(0) can return a valid non-null pointer, but this pointer cannot be dereferenced, nor used to store anything as the size of the object it points to is 0.
In both cases, your code has undefined behavior, which may or may not be a crash.

Related

initiations pointer to arrays

//1
char** p;
p[0]="Test";
//2
char** array;
array = realloc(array, sizeof(char*)*((*size)+1));
array[*size] = (char*)malloc(sizeof(char)*(strlen(input)+1));
Why does the first code fails in the second line, while the the second code works fine, doesn't array[*size] is just like p[0]?
Examining the code:
char **p; // Declared, but uninitialized
p[0] = "test"; // Setting value to it?
p is uninitialized, and as such, trying to access and set memory with it is UB, or undefined behavior. Failing is much better than potential alternatives.
For the second piece of code, assuming size is some pointer not included in the snippet.
char** array
array = realloc(array, sizeof(char*)*((*size)+1)); // Allocating.
array[*size] = (char*)malloc(sizeof(char)*(strlen(input)+1));
So, strictly speaking, calling realloc with an uninitialized pointer is UB, by chance array is equal to Null.
Note that:
If ptr is NULL, the behavior is the same as calling malloc(new_size).
As such, realloc will allocate a chunk of memory and pass it to array.
You then dereference the pointer (which is no longer pointing to Null but a valid spot in memory), and malloc it, which does not crash.
From the best guess, while this is undefined behavior, p is possibly Null in both cases, and the first one crashes when trying to dereference it, and the second one successfully gets malloced.

Constant Value assignment to Integer Pointer in C works for this case

I got an surprising observation, the following code is getting a Segmentation Fault
#include<stdio.h>
void main() {
int *i;
*i = 100;
printf("%u\n",i);
printf("%d\n",*i);
}
But not the below one.
#include<stdio.h>
void main() {
char* str;
int *i;
*i=100;
str = "Hello";
printf("%u\n",i);
printf("%s %d\n",str,*i);
}
Can Someone explains the behavior? I'm using gcc.
First of all, both the snippets cause undefined behavior because of the dereference of uninitialized pointer i.
In your first case, you're trying to dereference an uninitialized pointer i, so that is undefined behavior.
You're doing
*i = 100;
but think, where does i point to? Probably to some memory location which is not accessible from the process, so it is invalid memory access. This triggers the UB.
Same in the second snippet, too.
However, if you remove the usage of i from the second snippet, it will be OK.
After the proposed change, in the second snippet, you're storing the starting address of the string literal into the pointer variable, i.e, assigning it. So, it is perfectly OK.
For a statement like
str = "Hello";
you're not defererencing str here, rather, assigning a pointer value to str, which is perfectly fine.
That said,
according to the C standard, for a hosted environment, void main() is not a conforming signature, you must use int main(void), at least.
A statement like printf("%u\n",i); also invokes undefined behaviour in it's own way. In case you want to print the pointer, you must use the %p format specifier and cast the argument to void*.
Your both programs will cause undefined behavior because of following reasons.So will not get the correct result.
1) Dereferencing uninitialized pointer *i = 100; is undefined behavior . In your both examples you are dereferencing pointer i before initializing it. Therefore first initialize pointer using & operator and after use it in your code.
2) Printing a pointer value using the conversion specifier for an unsigned. You should use %p instead.
i has not been initialized to point to any memory location in particular, so it is not a valid pointer value. Attempting to write through an invalid pointer leads to undefined behavior, meaning the result can be anything - your code may crash outright, it may corrupt data, it may have garbled output, or it may appear to work with no issues.

Behavior of char pointer [duplicate]

This question already has answers here:
No out of bounds error
(7 answers)
Closed 6 years ago.
I am really confused about the following:
char *list = malloc(sizeof(char));
list[0] = 'a';
list[1] = 'b';
printf("%s\n", list);
My expectation was some kind of undefined behavior, because list has only memory for 1 char "object".
But the actual output is ab. Why can I access list[1] when list only has allocated memory for one char?
As per your memory allocation of sizeof(char) bytes (and considering the allocation is success),
list[1] = 'b';
is out-of-bound access, which invokes undefined behavior. There can be no expectation from a program causing UB. It can do anything, absolutely anything.
That said,
sizeof(char) is defined (guranteed) to be 1 in C standard.
Check for the success of malloc() before using the return value. Otherwise, the first access, list[0] itself will invoke UB as you'll end up dereferencing an invalid pointer (i.e., accessing invalid memory)
Passing a pointer to a non-null-terminated char array as argument to %s also invokes UB.

C - strcpy with malloc size less than argument's size [duplicate]

This question already has answers here:
I can use more memory than how much I've allocated with malloc(), why?
(17 answers)
Closed 7 years ago.
char* init_array()
{
const int size = 5;
char *p = (char*) malloc(size * sizeof(char));
strcpy(p, "Hello, world! How are you?");
return p;
}
with size = 5, malloc should get 5 free chars from memory, but given string does not fit into 5 chars, yet it works.
My question is why? First I thought the result would get truncated but p is the fully string, not just "Hello" or "Hell\0"
I'm using GCC on Linux. Is it related to the compiler or it is standard stuff?
It's called undefined behavior, since it's undefined sometimes it works. Yes you can write past a memory block in c, but that's illegal because it invokes undefined behavior, the behavior is therefore not predictable and your program might or might not work.
What you expect from strcpy() doesn't happen because strcpy() copies as many characters as it finds before the '\0' terminating byte, it doesn't care if the destination buffer is large enough, that's something you must be responsible about.
If you want to copy an exact number of bytes (let's say 5) you can use
memcpy(p, "Hello, this string is very large but it doesn't matter", 5);
but beware that p is not a valid string after that, because it has no terminating '\0'.
You also have 2 other common bad practice that new c programmers do
You don't need to cast the return value from malloc().
You don't need to use sizeof(char) because it's 1 by definition.
So,
p = malloc(size);
should be enough to allocate space for a size - 1 characters string.
What you are experiencing is a buffer overflow
In short, you write to invalid memory addresses invoking Undefined Behavior. Anything can happen.
It seems that it worked but in fact your code invokes undefined behavior. You are writing data to unallocated memory location.
You should note that in
strcpy(str1, str2);
strcpy has no way to check whether the string pointed to by str2 will fit into the character array str1. In your case it will continue to copy the characters from "Hello, world! How are you? to past the array p points to.

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