Behavior of char pointer [duplicate] - c

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.

Related

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

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.

C malloc syntax [duplicate]

This question already has answers here:
Do I cast the result of malloc?
(29 answers)
Closed 7 years ago.
str = (char *) malloc(15);
If I do not type (char *), is there any difference in my program?
If I try to free the memory with free(str), linux freezes unexpectedly after running program.
If you program in C, it does not make a difference, the preferred syntax is actually
char *str = malloc(15);
If you were programming in C++, the return value from malloc() would not be cast implicitly as char * for storing into str. But in C++, you should not use malloc() anyway, you should write str = new char[15]; and free this memory with delete []str;.
A potential reason for free(str); to cause undefined behavior is your writing to the array pointed to by str beyond the first 15 bytes.
Use valgrind to help track down where this happens.
char *malloc(size)
unsigned size;
malloc() is used to allocate a certain number, size, of free memory and return a pointer to the beginning of it. The malloc() function is part of the dynamic allocation routines.
If an allocation request fails- that is, if there is insufficient memory to fill the request- a null pointer is returned.
You always must be very careful to make sure that you receive a valid pointer from malloc().
This is the general form of a program that will allocate 80 bytes of memory and then free them.
main()
{
char *p;
p= malloc(80);
if(!p){ printf("out of memory\n"); exit(2); }
.
.
.
free(p);
}

Difference between initializing a string with (char *)malloc(0) and NULL

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.

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.

malloc(0) actually works? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
what’s the point in malloc(0)?
Why does malloc(0) actually return a valid pointer for writing ?
char *str = NULL;
str = (char*)malloc(0); // allocate 0 bytes ?
printf("Pointer of str: %p\n", str);
strcpy(str, "A very long string ...................");
printf("Value of str: %s", str);
free(str); // Causes crash if str is too long
Output:
Pointer of str: 0xa9d010
Aborted
Value of str: A very long string ...................
When str is shorter then it just works as it should.
BTW: For compiling I used GCC with "-D_FORTIY_SOURCE=0 -fno-stack-protector"
*** glibc detected *** ..: free(): invalid next size (fast): 0x0000000000a9d010 ***
It is undefined behavior to dereference the pointer returned by malloc(0).
From the C Standard:
(C99, 7.20.3p1) "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."
Why does malloc(0) actually return a valid pointer for writing?
It doesn't return a valid pointer for writing. It returns a valid pointer for not using it. Or it may return NULL as well since the C standard specifies this case to be implementation defined.
malloc() is supposed to return a void* pointer. And it faithfully does that. But leads to UB when you dereference it.

Resources