涉及默认复制构造函数的代码应该是段错误,但工作正常
Code involving default copy constructor should segfault, but works just fine
我做了 运行 一个小实验以更好地理解什么时候 constructors/destructors 被隐式调用,我发现了一些非常奇怪的东西。
以下代码在调用 myFunction()
时调用默认复制构造函数。在退出 myFunction() 的范围之前,我的用户定义 ~myClass()
被调用,它应该在 dangerData
上调用 free()
。但是,这似乎并没有释放 dangerData
!
#include <cstdio>
#include <cstdlib>
class myClass {
static int nextid;
int myID;
char *dangerData;
public:
myClass() {
myID = nextid++;
printf("Constructing myClass number %d\n", myID);
dangerData = (char *)malloc(1024);
dangerData[12] = 0;
}
~myClass() {
printf("Destructing myClass number %d. dangerData = %p\n", myID, (void *) dangerData);
dangerData[12] = 'a'; //Mark the array
free(dangerData); //This call chould free the array... but it doesn't!
}
void msg() {
printf("Message from myClass number %d. dangerData[12] = %d\n", myID, dangerData[12]);
}
};
int myClass::nextid = 1;
void myFunction(myClass param) {
param.msg();
}
int main() {
myClass m;
myFunction(m); //Calls default copy constructor
m.msg();
return 0;
}
这段代码的输出是:
Constructing myClass number 1
Message from myClass number 1. dangerData[12] = 0
Destructing myClass number 1. dangerData = 02f71458. dangerData[12] = 0
Message from myClass number 1. dangerData[12] = 97
Destructing myClass number 1. dangerData = 02f71458. dangerData[12] = 97
对析构函数的第一次调用是肯定在malloc数组上调用free()
,但是在[=19=中调用m.msg()
] 仍然可以在没有段错误的情况下访问它!
这应该发生吗?
Is this supposed to be happening?
没有什么特别的是 "supposed" 或者更确切地说 "expected" 在这里发生 - 你正在调用未定义的行为,所以任何事情 都可能 发生,包括 "nothing".
the call to m.msg() in main() can still access it without segfaulting!
这并不令人惊讶(但同样,您不应该指望任何东西)。释放内存或多或少会告诉 OS 该内存可以 reused/overwritten 自由使用。你的编译器,OS 和它们的设置之间越是关注速度而不是安全,他们投入到将这个内存标记为不可访问的工作就越少,而且由于你只是使用了那个确切的内存位置,你将不得不 运行 在非常严格的 OS 检查下甚至会出现段错误。在两次 msg()
调用之间的时间里,第 13 个字符也极不可能被覆盖,因此您很可能会再次读回相同的内容。
但这一切仅适用于这个小例子,同样,没有什么可依赖的。未定义的行为(有点不幸)并不自动意味着 "your program will segfault now"。它可能会,也可能两分钟后在完全不同的部分发生段错误,或者默默地输出错误结果,或者格式化你的硬盘。或者它可能 运行 如您所愿,这一次。
我做了 运行 一个小实验以更好地理解什么时候 constructors/destructors 被隐式调用,我发现了一些非常奇怪的东西。
以下代码在调用 myFunction()
时调用默认复制构造函数。在退出 myFunction() 的范围之前,我的用户定义 ~myClass()
被调用,它应该在 dangerData
上调用 free()
。但是,这似乎并没有释放 dangerData
!
#include <cstdio>
#include <cstdlib>
class myClass {
static int nextid;
int myID;
char *dangerData;
public:
myClass() {
myID = nextid++;
printf("Constructing myClass number %d\n", myID);
dangerData = (char *)malloc(1024);
dangerData[12] = 0;
}
~myClass() {
printf("Destructing myClass number %d. dangerData = %p\n", myID, (void *) dangerData);
dangerData[12] = 'a'; //Mark the array
free(dangerData); //This call chould free the array... but it doesn't!
}
void msg() {
printf("Message from myClass number %d. dangerData[12] = %d\n", myID, dangerData[12]);
}
};
int myClass::nextid = 1;
void myFunction(myClass param) {
param.msg();
}
int main() {
myClass m;
myFunction(m); //Calls default copy constructor
m.msg();
return 0;
}
这段代码的输出是:
Constructing myClass number 1
Message from myClass number 1. dangerData[12] = 0
Destructing myClass number 1. dangerData = 02f71458. dangerData[12] = 0
Message from myClass number 1. dangerData[12] = 97
Destructing myClass number 1. dangerData = 02f71458. dangerData[12] = 97
对析构函数的第一次调用是肯定在malloc数组上调用free()
,但是在[=19=中调用m.msg()
] 仍然可以在没有段错误的情况下访问它!
这应该发生吗?
Is this supposed to be happening?
没有什么特别的是 "supposed" 或者更确切地说 "expected" 在这里发生 - 你正在调用未定义的行为,所以任何事情 都可能 发生,包括 "nothing".
the call to m.msg() in main() can still access it without segfaulting!
这并不令人惊讶(但同样,您不应该指望任何东西)。释放内存或多或少会告诉 OS 该内存可以 reused/overwritten 自由使用。你的编译器,OS 和它们的设置之间越是关注速度而不是安全,他们投入到将这个内存标记为不可访问的工作就越少,而且由于你只是使用了那个确切的内存位置,你将不得不 运行 在非常严格的 OS 检查下甚至会出现段错误。在两次 msg()
调用之间的时间里,第 13 个字符也极不可能被覆盖,因此您很可能会再次读回相同的内容。
但这一切仅适用于这个小例子,同样,没有什么可依赖的。未定义的行为(有点不幸)并不自动意味着 "your program will segfault now"。它可能会,也可能两分钟后在完全不同的部分发生段错误,或者默默地输出错误结果,或者格式化你的硬盘。或者它可能 运行 如您所愿,这一次。