Странная ошибка при передаче двойных указателей на функцию в C - PullRequest
0 голосов
/ 18 июня 2020

Ошибка:
При передаче двойного указателя функции значение полей, на которые указывает указатель, кажется, зависит от некоторой локальной переменной функции.
Точнее, когда я комментирую строку L (в функции «function»)
Вывод:

In the main function: 1
In the function: 1

Но когда я раскомментирую ту же строку,
Вывод:

In the main function: 1
In the function: 0

программа:

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);
}

То, что я пробовал:

  • Я думал, что получаю случайные результаты, но это было не так, поскольку я постоянно получаю один и тот же результат.
  • Я попытался расшифровать код языка ассемблера, но для меня это было слишком сложно c.

Окружение:

  • компилятор: gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
  • операционная система: linux mint

Ответы [ 2 ]

4 голосов
/ 18 июня 2020

Здесь:

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
}

Переменная f не существует, когда функция initialize возвращается, поэтому вы возвращаете адрес несуществующей переменной. Использование адреса будет неопределенным поведением, т. Е. Может произойти что угодно, и в общем случае это невозможно объяснить.

В конкретной c системе мы можем сделать некоторые предположения. Я предполагаю, что как только вы добавляете строку с новой переменной, она перезаписывает место в памяти, где раньше хранилось f. Без новой переменной место хранения f остается прежним.

1 голос
/ 18 июня 2020

Функция initialize

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

может вызывать неопределенное поведение, поскольку она возвращает указатель на локальную переменную. И, кроме того, у него утечка памяти.

Сначала была выделена память и ее адрес был назначен переменной temp

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

Затем указатель был переназначен

    temp = &f;

Таким образом, выделенная память не освобождается.

Указатель назначается адресом локальной переменной

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

После выхода из функции переменная f перестает существовать. Значит, указатель temp имеет недопустимое значение.

Похоже, вы имеете в виду следующее

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

Если внести изменения, вы получите ожидаемый результат.

#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 );
}

Вывод программы:

In the main function: 1
In the function: 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...