简体   繁体   中英

Assigning values to C pointers using malloc without variable initialization

From this question , I understand why the code below may not work:

int *ptr;
*ptr = 1000;
printf("%d", *ptr);

when I compiled and run it using: gcc file.c; ./a.out gcc file.c; ./a.out I got:

Segmentation fault (core dumped)./a.out

ptr here may point to a random location without an initialized variable. Is that correct?

However, when using malloc() that issue does not occur.

int *ptr = malloc(sizeof(int));
*ptr = 1000;
printf("%d", *ptr);

Does malloc initialize the variable that its pointer is pointing to?

Short answer: No

malloc does not initialize the variable. It just allocate the memory. You can put integer into the function, for example malloc(8) , it will just allocate 8 bytes for later use. If you look further into the malloc function, it actually returns void* datatype. It can be later typecasted into other datatype.

From your code malloc(sizeof(int)) , actually sizeof(int) returns an integer for the size of the datatype/variable you put into it.

CASE I :
Code:

int *ptr;
*ptr = 1000;

*ptr means you are dereferencing ptr pointer. Dereferencing an uninitialised pointer is undefined behaviour . An undefined behavior includes it may execute incorrectly (either crashing or silently generating incorrect results), or it may fortuitously do exactly what the programmer intended.

CASE II :
Code:

int *ptr = malloc(sizeof(int));
*ptr = 1000;

malloc allocates memory block (of size in bytes) and returns the pointer to the beginning of newly allocated memory on success. The newly allocated block of memory is not initialised.

When doing this:

int *ptr = malloc(sizeof(int));

Assume malloc call is success and it returned pointer to beginning of newly allocated memory. This returned pointer will be assigned to ptr pointer. So, now the ptr pointer is initialised though the memory it is pointing to is uninitialised .
Since, the ptr pointer is pointing to a valid memory location, you can dereference it and access it.

In this statement

*ptr = 1000;

dereferencing ptr and assigning 1000 to that memory location. Now, the memory location which ptr pointer is pointing to contain value 1000 . Accessing this value perfectly fine.


Additional:

Follow the good programming practice - Always check the malloc return. You should do:

  int *ptr = malloc (sizeof (int));
  if (NULL == ptr) {
    exit(EXIT_FAILURE); // or whatever you want to do at malloc failure do it here
  }

The post you linked explains it more or less. One thing is doesn't touch on is undefined behavior - which is exactly what will happen in your version without malloc .

All sorts of things can go wrong if you try to use such a pointer - you haven't said where it should point to. It could point literally anywhere.

This line:

int *ptr = malloc(sizeof(int));

is indeed an initialization. What's happening here is two things: (1) malloc is reserving space in memory so that you can subsequently use the pointer and (2) its returning the starting address of that memory.

The address gets assigned to ptr - which is itself a variable. And, like all variables, you can't use them uninitialized. If you do, that's invalid code and therefore, it results in undefined behavior.

Let's drill down this point a little more:

If you don't call malloc , your pointer is invalid and should not be used. To prove this, try compiling your code, say using good old gcc .

If you run:

gcc program.c  # no flags

it will compile -- but just because gcc gave you a binary, it doesn't mean it will do what you want. When you run it, it will (most of the time) fail miserably.

However, if you run:

gcc -Wall program.c  # enable warnings

it will warn you that ptr is being unused uninitialized. But, it will still produce a binary which you can run - resulting in the same thing as before.

Finally, if you run:

gcc -Wall -Werror program.c  # enable warnings and turn them into errors

it will again warn you of the same thing but this time, it won't produce a binary -- and this is what you really want in this situation. Here, gcc is telling you that something is really very wrong and that your code is simply not valid.

Now, back to the point about undefined behavior. Once you've compiled your invalid code (using either of the first two methods - BTW please never do this), running it will often give you a "segmentation fault" (seg fault). However, it doesn't have to and there are no guarantees as to what your program will do. All variables, including pointers, need to be initialized.

BTW, if you look at this post, it tells you why you need to call malloc here at all -- its because you're allocating memory dynamically, so it will be in the heap rather than on the stack.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM