0

Bug:
While passing a double pointer to a function the value of the fields that the pointer is pointing to seems to be dependent on some local variable of the function.
More specifically when I comment the line L(in the function "function")
Output:

In the main function: 1
In the function: 1

But when I uncomment the same line,
Output:

In the main function: 1
In the function: 0

program:

typedef struct s{
    int *value; 
}s;


s** initialize()
{
    s** temp = (s**)malloc(sizeof(s*));
    s* f = (s*)malloc(sizeof(s));
    f->value = NULL;
    temp = &f;
    return temp;
}

void function(s** what)
{

//Line L:   size_t count = 0;
    printf("In the function: %d\n", (*what)->value == NULL);
}

int main()
{
    s** m = initialize();
    printf("In the main function: %d\n", (*m)->value == NULL);
    function(m);
}

What I have tried:

  • I thought that I am getting random outputs, but that was not the case as I am consistently getting the same output.
  • I tried deciphering the assembly language code but that was too cryptic for me.

Environment:

  • compiler: gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
  • operating system: linux mint
xrfxlp
  • 421
  • 5
  • 15

2 Answers2

4

Here:

s** initialize()
{
    s** temp = (s**)malloc(sizeof(s*));
    s* f = (s*)malloc(sizeof(s));
    f->value = NULL;
    temp = &f;          // temp is now the address of a local variable
    return temp;        // now temp is returned
                        // that's undefined behavior when the returned
                        // pointer is used
}

The variable f doesn't exist when the initialize function returns, so you are returning the address of a non-existing variable. Using the address will be undefined behavior, i.e. anything can happen and there is no way in general to explain it.

On a specific system, we can do some guessing. My guess is that once you add the line with a new variable, it overwrites the memory location where f used to be stored. Without the new variable the location where f used to be stored is still the same.

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
1

The function initialize

s** initialize()
{
    s** temp = (s**)malloc(sizeof(s*));
    s* f = (s*)malloc(sizeof(s));
    f->value = NULL;
    temp = &f;
    return temp;
}

can invoke undefined behavior because it returns pointer to a local variable. And moreover it has a memory leak.

At first a memory was allocated and its address was assigned to the variable temp

    s** temp = (s**)malloc(sizeof(s*));

Then the pointer was reassigned

    temp = &f;

So the allocated memory is not freed.

The pointer is assigned by the address of a local variable

    s* f = (s*)malloc(sizeof(s));
    //...
    temp = &f;

After exiting the function the variable f will not alive. So the pointer temp has an invalid value.

It seems what you mean is the following

s** initialize()
{
    s** temp = (s**)malloc(sizeof(s*));
    s* f = (s*)malloc(sizeof(s));
    f->value = NULL;
    *temp = f;
    return temp;
}

If to make the changes you will get the expected result.

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

typedef struct s{
    int *value; 
}s;

s** initialize()
{
    s** temp = (s**)malloc(sizeof(s*));
    s* f = (s*)malloc(sizeof(s));
    f->value = NULL;
    *temp = f;
    return temp;
}

void function(s** what)
{

//Line L:   size_t count = 0;
    printf("In the function: %d\n", (*what)->value == NULL);
}

int main( void )
{
    s** m = initialize();
    printf("In the main function: %d\n", (*m)->value == NULL);
    function(m);

    free( *m );
    free( m );
}

The program output is

In the main function: 1
In the function: 1
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335