Возвращаемое значение 3221225477 происходит, когда я использую указатель для структурирования указателя в коде

Что не так в моем коде ниже?

Там нет никаких ошибок или предупреждений, когда я компилирую его компилятором Dev C++. Но после запуска моей программы возникает ошибка выполнения и следующий текст возвращаемого значения:

Процесс завершен через 5,1 секунды с возвращаемым значением 3221225477
Нажмите любую клавишу для продолжения.,,

Есть идеи, что не так?

Когда я использую функцию отладки, возникает ошибка в этой строке:

printf("Value of (*pointerToMyOwnStructPointer)->a = %d\n", (*pointerToMyOwnStructPointer)->a);

Мой код:

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

typedef struct{
    int a;
    int b;
}myIntegers_t;

int main (void)
{
    myIntegers_t *myOwnStructPointer = NULL;
    myIntegers_t **pointerToMyOwnStructPointer = NULL;

    myOwnStructPointer = (myIntegers_t*)malloc(sizeof(myIntegers_t));

    if (myOwnStructPointer > 0)
    {   
        myOwnStructPointer->a = 2;
        myOwnStructPointer->b = 8;

        printf("Value of myOwnStructPointer->a = %d\n", myOwnStructPointer->a);
        printf("Value of myOwnStructPointer->b = %d\n", myOwnStructPointer->b);

        pointerToMyOwnStructPointer = (myIntegers_t**)myOwnStructPointer;

        printf("\n");
        printf("Value of (*pointerToMyOwnStructPointer)->a = %d\n", (*pointerToMyOwnStructPointer)->a);
        printf("Value of (*pointerToMyOwnStructPointer)->b = %d\n", (*pointerToMyOwnStructPointer)->b);  
    }
    else
    {
        return -1;
    }

    return 0;
}

5 ответов

В вашем коде,

 pointerToMyOwnStructPointer = (myIntegers_t**)myOwnStructPointer;

очень неправильно. Вы должны изменить это на

pointerToMyOwnStructPointer = &myOwnStructPointer;

чтобы получить ожидаемое поведение.

Разрабатывать,

  • myOwnStructPointer указатель на тип
  • pointerToMyOwnStructPointer является указателем на указатель на тип.

они не эквивалентны. Просто потому что они оба указатели, вы не можете просто привести значение одного типа к другому и ожидать, что это сработает. Актерский состав неправильный (и даже не обязательный). Так,

  • Не бросать
  • Включить предупреждения компилятора.

В большинстве случаев ваш компилятор спасет вас, по крайней мере, с помощью предупреждения.


Примечание: пожалуйста, посмотрите, почему бы не бросить возвращаемое значение malloc() и семья в C,

Там были бы ошибки или предупреждения, если у вас не было этого приведения в назначении

pointerToMyOwnStructPointer = (myIntegers_t**)myOwnStructPointer;

Это потому что myOwnStructPointer это указатель на вашу структуру, но pointerToMyOwnStructPointer это указатель на указатель на вашу структуру, и эти два типа полностью несовместимы.

Компилятор интерпретирует это так:

+ ----------------------------- + + -------------- + + -------+
| pointerToMyOwnStructPointer | -> | какой-то адрес | -> | структура |
+-----------------------------+    +--------------+    +------- +

Поэтому, когда вы делаете свое назначение, а затем используете pointerToMyOwnStructPointer это приводит к неопределенному поведению, так как не указывает на указатель.


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

Это был мой оригинальный код, и теперь он работает после того, как я добавил один знак "&". Большое спасибо за вашу поддержку!

Есть комментарии по поводу этого кода? Я думаю, что есть приведение к возвращаемому значению функции malloc... это проблема?

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

#define OK 1
#define FAILURE 0

typedef struct{
    int a;
    int b;
}myIntegers_t;

void * open(void);
int close(void ** pointerToMyOwnStructPointer );

void main(void)
{
    void * myVoidParameter;

    if(myVoidParameter = open())
    {
        printf("\n\nPORT OPENED SUCCESSFULLY!!\n\n");

        myIntegers_t ** pointerToMyVoidParameter = (myIntegers_t**)&myVoidParameter;

        printf("\n");
        printf("Value of pointerToMyVoidParameter->a = %d\n", (*pointerToMyVoidParameter)->a);
        printf("Value of pointerToMyVoidParameter->b = %d\n", (*pointerToMyVoidParameter)->b);

        if(close(&myVoidParameter))
        {
            printf("\n\nPORT CLOSED SUCCESSFULLY!!\n");
        }
        else
        {
            printf("\n\nFAILURE IN PORT CLOSING!!!\n");
        }
    }
    else
    {
        printf("\n\nFAILURE IN PORT OPENING!!!\n");
    }
}

void * open(void){

    myIntegers_t *myOwnStructPointer = (myIntegers_t*)malloc(sizeof(myIntegers_t));

    if (myOwnStructPointer)
    {   
        myOwnStructPointer->a = 2;
        myOwnStructPointer->b = 8;

        printf("\n");
        printf("Value of myOwnStructPointer->a = %d\n", myOwnStructPointer->a);
        printf("Value of myOwnStructPointer->b = %d\n", myOwnStructPointer->b);

        return myOwnStructPointer;
    }
    else
    {
        return NULL;
    }
}

int close(void ** pointerToMyOwnStructPointer ){
    int result = OK;
    myIntegers_t ** descriptor = (myIntegers_t**)pointerToMyOwnStructPointer;

    if(descriptor == NULL || *descriptor == NULL)
    {
        return FAILURE;
    }

    printf("\n");
    printf("Value of descriptor->a = %d\n", (*descriptor)->a);
    printf("Value of descriptor->b = %d\n", (*descriptor)->b);


    (*descriptor)->a = 0;
    (*descriptor)->b = 0;
    free((void*)*descriptor);
    *pointerToMyOwnStructPointer = NULL;

    return result;  
}

Ответьте на свой новый вопрос.

Вы должны всегда приводить malloc в C++ и никогда не приводить malloc в c, как уже было сказано Shreevardhan и Sourav Ghosh.

Все ваши пустоты * на самом деле myIntegers_t*, поэтому сделайте их myIntegers_t*. Это выгодно как для читателя, так и позволяет компилятору обнаруживать ошибки.

Все ваши пустоты ** на самом деле myIntegers_t**. Смотри выше.

Если содержимое a и b не является секретным, вам не нужно устанавливать их в 0 перед освобождением. И для free не требуется указывать аргумент void *, поскольку void * совместим со всеми указателями. Нужно только, чтобы указатель был сделан malloc, calloc или realloc.

Я не думаю, что дополнительный дескриптор помогает, кроме, возможно, читабельности, но затем просто переименуйте pointerToMyOwnStructPointer.

Только предложение по улучшению

Кроме того, правильный malloc способ распределения будет

myIntegers_t * myOwnStructPointer = malloc(sizeof(myIntegers_t));
if (myOwnStructPointer == NULL)
    return 1;

. . .    // else do something with myOwnStructPointer;
Другие вопросы по тегам