Потеря ссылки на указатель на член структуры? (в c) - PullRequest
1 голос
/ 01 марта 2020

Я делаю небольшой проект просто для удовольствия о OO в C. Проблема, с которой я сталкиваюсь, довольно странная для меня. Ниже приведена вся программа.

При компиляции и запуске все «методы» работают должным образом ... до тех пор, пока не достигнут первых «путов». В этот момент «методы» утратили ссылку на «я» в этом месте.

Я не уверен, почему это работает до тех пор, но не после. Стоит отметить, что повторное выполнение конструктора до второго «пута» заставит его работать. Цепочки 'if' ясно показывают, что методы работают, потому что они правильно устанавливают новые строки.

Я понимаю, что это можно исправить, просто передавая адрес объекта через параметры в методы, но это Как бы то ни было, я хотел бы найти изящный способ сделать это без этого.

#include <stdio.h>
//-----class_a--------------------------------------------------------------//
typedef struct{
    char*   string;
    char*   (*get_string)();
    char*   (*set_string)(char*);
} class_a;

void constructor_class_a(class_a *self, char* string){

    self->string            = string;

    char* get_string(){
        return self->string;
    } self->get_string      = get_string;

    char* set_string(char* new_string){
        return self->string = new_string;
    } self->set_string      = set_string;
}
//--------------------------------------------------------------------------//
int main(){
    class_a object_a;
    constructor_class_a(&object_a, "default string");

    printf("string: %s\n", object_a.get_string());
    if (object_a.get_string()=="default string"){
        object_a.set_string("temporary string");
        if (object_a.get_string()=="temporary string"){
            object_a.set_string("final string");
            if (object_a.get_string()=="final string"){
                printf("string: %s\n", object_a.get_string());
            }
        }
    }

    printf("%s", object_a.get_string());
    return 0;
}

Я пытался сделать это безрезультатно (включая члена int init для ' класс '):

char* get_string(){
    static class_a *self2 = {0};
    if (!self2->inti){
        *self2 = *self;
        self2->init = 1;
    }
    return self2->string;
} self->get_string      = get_string;

1 Ответ

2 голосов
/ 01 марта 2020

Проблема в том, что вы пытаетесь использовать вложенные функции, которые не являются частью языка C, а расширением G CC, но используют их неправильно. Время их жизни заканчивается в конце блока, в который они вложены, и любое использование указателя функции на них после окончания их жизни имеет неопределенное поведение.

Даже если бы это сработало, это была бы ужасная идея , поскольку способность иметь указатели на вложенные функции обязательно зависит от наличия исполняемого стека, который не рекомендуется использовать, поскольку он делает большинство видов уязвимостей тривиальными для использования. Это одна из многих причин, по которым clang и другие компиляторы отказываются копировать эту функцию G CC, и почему она по существу мертва.

...