【发布时间】:2017-11-23 11:11:49
【问题描述】:
我想问一个简单的问题。请考虑随附的代码。在 main 函数中,指向结构的指针通过 ctor1 或 ctor 2 以两种不同的方式构建。在这两种情况下,无论我使用哪个构造函数,程序都可以正常工作。
ctor1 工作的原因是结构实例的内存分配在函数框架之外(即在堆中)。因此,在ctor1终止后,它将在main函数中可用。
我的问题归结为 ctor2 函数。据我所知,局部变量“myPtr foo”预计会在函数结束时被销毁。因此,从现在开始,“那个”指针应该不指向任何东西。然而,执行完程序后,我发现两个构造函数都完美无缺。
显然,有一个微妙的细节让我无法理解。你能解释一下为什么函数 ctor2 有效吗? 提前谢谢!
#include <stdio.h>
#include <malloc.h>
int _method(void) {
return 0;
}//_foo
typedef struct vTable {
int (*method)(void);
} myPtr;
myPtr *ctor1(void) {
myPtr *foo;
foo = (myPtr*)malloc(1 * sizeof(myPtr));
foo->method = &_method;
return foo;
}//ctor1
void ctor2(myPtr *that) {
myPtr foo = { &_method };
that = &foo;
return;
// having reached the function end "foo" is destroyed
// and "that" should point to nothing, supposedly
}//ctor2
int dtor(myPtr *foo) {
free(foo);
foo->method = NULL;
foo = NULL;
return 0;
}//dtor
int main(void) {
myPtr *vPtr;
// it works as expected
vPtr = ctor1();
printf("%p\n\n", vPtr); // 003E0F68
dtor(vPtr);
// it works surprisingly enough
ctor2(vPtr);
printf("%p\n", vPtr); // 003E0F68
printf("%p\n", vPtr); // 003E0F68
// it keeps on working
printf("%p\n", vPtr); // 003E0F68
dtor(vPtr);
return 0;
}//main
【问题讨论】:
-
使用指向已销毁对象的指针是未定义的行为。如果它看起来有效,那只是偶然,可能是因为内存还没有被重用。
-
ctor2函数不起作用,原因之一不是指向局部变量:您将指针传递给函数按值我>。您只需修改函数内部的 局部变量that。main函数中的vPtr变量根本没有被修改。 -
free(foo); foo->method = NULL;导致未定义的行为。释放对象后不能尝试修改它 -
感谢您的回复。 Quantum Leaps 在本文第 8 页中使用了类似的技术。state-machine.com/doc/AN_OOP_in_C.pdf 我想知道它是否合法。
-
@user3633207:该文章中的代码传递了一个指向包含
vptr的结构的指针,然后对其进行修改。在您指向的对象中为vptr赋值会更改对象的vptr成员。您的代码在参数中传递了vptr。更改参数只会更改参数,它是传递值的副本。