0

I try to malloc an array functionally, and this function also can check whether the memory is enough or not.

The first code block can't work. When it executes " *pi = 5 ", the compiler shows this error message " Thread 1: EXC_BAD_ACCESS(code=1, address=0x0) " .

 #include <stdio.h>
 #include <stdlib.h>

 void malloc_and_check(int *var)
 {
     if(!(var = (int*)malloc(sizeof(int))))
     {
        fprintf(stderr, "Insufficient Memory\n");
        exit(EXIT_FAILURE);
     } 
 }

 int main(int argc, const char * argv[]) 
 {
    int *pi;
    malloc_and_check(pi);
    *pi = 5;
    printf("%d", *pi);
    free(pi);
 }

However, the codes as below can work normally.

    #include <stdio.h>
    #include <stdlib.h>

    int main(int argc, const char * argv[])
    {
        int *pi;

        if(!(pi = (int*)malloc(sizeof(int))))
        {
            fprintf(stderr, "Insufficient Memory\n");
            exit(EXIT_FAILURE);
        }

        *pi = 5;
        printf("%d", *pi);
        free(pi);
    }

What are the difference between them? Thanks!

the_unknown_spirit
  • 2,518
  • 7
  • 34
  • 56

4 Answers4

2

When you pass the int * var into malloc_and_check you are updating a local copy of the pointer so the original is unchanged. You can fix this in two ways:
(a) return the pointer from malloc_and_check

int * malloc_and_check()
{
    int * var = 0;
    if(!(var = (int*)malloc(sizeof(int))))
    {
        fprintf(stderr, "Insufficient Memory\n");
        return 0;
    } 
    return var;
}  

Then you would call it as

pi = malloc_and_check();

(b) pass in a pointer to the pointer

void malloc_and_check(int ** var)
{
    if(!( *var = (int*)malloc(sizeof(int))))
    {
        fprintf(stderr, "Insufficient Memory\n");
        exit(EXIT_FAILURE);
    } 
}  

Then you would pass it in as

 malloc_and_check(&pi);
John D
  • 1,627
  • 1
  • 11
  • 10
  • Yes, another way to explain it is that when anything is passed as a function parameter, the function receives a ***copy*** (with its very own, and very different address). In the case of an allocated pointer, it makes no difference, because the ***value*** of the pointer still points to the original block of memory. However, with an unallocated pointer, the address returned by `malloc` is assigned to the copy of the pointer and there is no correlation to the original pointer address back in `main`. (which also results in a memory leak) – David C. Rankin Oct 26 '16 at 04:53
1

You are trying to pass the pointer by value (pass by value). You need to pass a double pointer to the function malloc_and_check. Due to this the value assigned to the pointer is not reflecting back in the caller.

Please modify your code as below:

 #include <stdio.h>
 #include <stdlib.h>

 void malloc_and_check(int **var)
 {
     if(!(*var = malloc(sizeof(int))))
     {
        fprintf(stderr, "Insufficient Memory\n");
        exit(EXIT_FAILURE);
     } 
 }

 int main(int argc, const char * argv[]) 
 {
    int *pi;
    malloc_and_check(&pi);
    *pi = 5;
    printf("%d", *pi);
    free(pi);
 }
Jay
  • 24,173
  • 25
  • 93
  • 141
1

The pointer var is allocated memory dynamically but it is local to the function malloc_and_check. The pointer pi in the function main will not get to know the address of the memory allocated to var. It is a bad access and may also result in crash sometimes.

try the code below to get the expected results :

#include <stdio.h>
 #include <stdlib.h>

 void malloc_and_check(int **var)
 {
     int *var1;
     if(!(var1 = (int*)malloc(sizeof(int))))
     {
        fprintf(stderr, "Insufficient Memory\n");
        exit(EXIT_FAILURE);
     } 
     else 
        *var = var1;
 }

 int main(int argc, const char * argv[]) 
 {
    int *pi;
    malloc_and_check(&pi);
    *pi = 5;
    printf("%d", *pi);
    free(pi);
 }
Darshan b
  • 157
  • 7
0

The change you make to var in the function is lost when the function returns. Either you need to pass var as a double pointer or you need to return a pointer from the function.

Example where the function returns a pointer:

 #include <stdio.h>
 #include <stdlib.h>

 int* malloc_and_check()
 {
     int *var;
     if(!(var = malloc(sizeof(int))))
     {
        fprintf(stderr, "Insufficient Memory\n");
        exit(EXIT_FAILURE);
     } 
     return var;
 }

 int main(int argc, const char * argv[]) 
 {
    int *pi;
    pi = malloc_and_check();
    *pi = 5;
    printf("%d", *pi);
    free(pi);
 }
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
  • Assigning the return is another option, but technically, that's the answer to a slightly different question. (but I won't split hairs) – David C. Rankin Oct 26 '16 at 04:48