Как исправить странное поведение анонимно созданной структуры при вызове в функции? - PullRequest
1 голос
/ 24 марта 2019

Я пытаюсь воссоздать принцип инкапсуляции в ANSI-C для образовательных целей.По сути, я делал какую-то структуру в файле .c :

struct _private
{
    unsigned char SizeInBytes;
    unsigned char* matrix;
    struct Stack* S;
    unsigned char ByteX;
};

, которая представляла переменные, которые я хотел видеть незаметными.Затем в файле .h внутри структуры (класса) я создал непрозрачный указатель:

struct Maze
{
    void* _private;
};

, который я назначу позже в функции конструктора следующим образом:

void* Maze_ctor(void* self, va_list *ap)
{
    struct Maze* this = self;

    this->DimX = va_arg(*ap, unsigned char);
    this->DimY = va_arg(*ap, unsigned char);

    this->_private = &(struct _private)          // passing address of struct to void*
    { 
        .SizeInBytes = this->DimX*this->DimY >> 1,
        .S = new(Stack),
        .ByteX = this->DimX % 8 > 0 ? this->DimX / 8 + 1 : this->DimX / 8
    };
    // 
    private.matrix = (unsigned char*)malloc(private.ByteX*this->DimY);
    S = new(Stack);     // this in my new() and it works similar to C++ new

    for (int i = 0; i < private.ByteX*this->DimY; i++)
        *(private.matrix + i) = 0;
}

На данный момент все работает нормально, но затем я пытаюсь вызвать метод Next ():

int Next(void* self, ...)
{
    struct Maze* this = self;

    struct _private *r = this->_private;

    short t;

    toBinary(this);          // after this point the struct private breaks
}

прототип toBinary ():

void toBinary(const void* self)
{
    // somehow char local is defined and equals to 204??
    struct Maze *this = self;
    struct _private *r = this->_private;

    unsigned char local;     // right after this point SizeInBytes equals to 204!
...
}

вопросесть: как решить эту проблему. Использование C ++ запрещено! для заинтересованных: вот новое ()

void* new(const void* _class,...)
{
    const struct Class* class = _class; // we need to convert pointer from void* to class* safely
    void *p = calloc(1, class->size);   // allocation of memory for class .using size param

    assert(p);                          // if Null -> throw an error
    *(const struct Class**)p = class;   // safe assignment of class pointer to (value) of p, to have memory and built in funcs
    if (class->ctor)                    // if has constructor with some dynal in it, execute with varargs on its input
    {
        va_list ap;
        va_start(ap, _class);           // 
        p = class->ctor(p, &ap);        // pass arguments as a list of pointers.
        va_end(ap);
    }
    return p;                           //returns a pointer to class pointer (weird but worx)
}

Ответы [ 2 ]

2 голосов
/ 24 марта 2019

Как указано в комментарии, проблема в том, что вы создали локальный объект и присвоили ему указатель this. За пределами этой функции значение this недопустимо.

Ваш код,

void* Maze_ctor(void* self, va_list *ap)
{
//....
// this creates a temporary object and will be destroyed after Maz_ctor returns.

this->_private = &(struct _private)          // passing address of struct to void*
{ 
    .SizeInBytes = this->DimX*this->DimY >> 1,
    .S = new(Stack),
    .ByteX = this->DimX % 8 > 0 ? this->DimX / 8 + 1 : this->DimX / 8
};
// ---
}
0 голосов
/ 24 марта 2019

Спасибо @Sami Kuhmonen за указание на динамическое распределение и @CS Pei за анализ ошибок.Что я сделал, чтобы это исправить:

struct Maze
{
    char _private[32]; // allocate the memory size of struct(32)
}


// assign values to void ptr
private.SizeInBytes = this->DimX*this->DimY >> 1;
private.S = new(Stack);
private.ByteX = this->DimX % 8 > 0 ? this->DimX / 8 + 1 : this->DimX / 8;
private.matrix = (unsigned char*)malloc(private.ByteX*this->DimY);

теперь это работает как задумано, но немного медленнее

...