在函数中调用时如何修复匿名创建结构的奇怪行为?
How to fix strange behavior of anonymously created structure, when called in function?
出于教育目的,我试图在 ANSI-C 中重新创建封装原则。我基本上做的是在 .c 文件中制作一些结构:
struct _private
{
unsigned char SizeInBytes;
unsigned char* matrix;
struct Stack* S;
unsigned char ByteX;
};
这代表了我不想看到的变量。然后在 .h 文件中的结构 (class) 我创建了一个不透明的指针:
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++!
对于感兴趣的人:这里是 new()
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)
}
正如评论中所指出的,问题在于您创建了一个本地对象并将其分配给一个指针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
};
// ---
}
感谢@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);
现在可以按预期工作,但速度稍慢
出于教育目的,我试图在 ANSI-C 中重新创建封装原则。我基本上做的是在 .c 文件中制作一些结构:
struct _private
{
unsigned char SizeInBytes;
unsigned char* matrix;
struct Stack* S;
unsigned char ByteX;
};
这代表了我不想看到的变量。然后在 .h 文件中的结构 (class) 我创建了一个不透明的指针:
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++! 对于感兴趣的人:这里是 new()
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)
}
正如评论中所指出的,问题在于您创建了一个本地对象并将其分配给一个指针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
};
// ---
}
感谢@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);
现在可以按预期工作,但速度稍慢