太逆天了,一定要记录一下
起因是这样:
我在写一个socket的服务端,我写了一个server类,socket是类的一个成员变量,在类初始化时创建,并在析构函数中关闭(划重点,等会要考)。简化后的定义如下:
class Server {
public:
Server() {};
Server(string root) {
// 创建套接字 并 绑定端口
this->serverSocket = socket(AF_INET, SOCK_STREAM, 0);
//中间省略一堆配置
bind(this->serverSocket, (sockaddr*)&serverAddress, sizeof(serverAddress);
}
~Server() {
closesocket(this->serverSocket);
}
void working() {
if (listen(this->serverSocket, 3) < 0) {
cout << "Listen error";
}
}
private:
SOCKET serverSocket;
};
为什么要定义一个空初始化?Server() {};
请看下面的代码:
int main() {
Server server;
try {
server = Server(root); //root是一个字符串路径,指示远程库的根目录
break;
}
catch (const exception& error) {
cout << error.what() << endl;
cout << "Please retype." << endl;
}
server.working();
return 0;
}
可以看到我用了try
,因为我希望在server初始化时进行错误检查,包括路径合不合法、套接字创建成不成功等等。但问题也就出在这里
根据C++的内存管理,try
代码块内部定义的变量是个局部变量,出了try
就会被销毁,所以如果我不在try
外部先声明server
,那么后面的代码就拿不到server
变量。但我只在外部声明,并不进行初始化,所以就定义了一个空初始化。
嗯,这样子写,代码是合法了,不报错了。但问题依然存在:在try
代码块内部定义的server
实例在出了try
之后还是会被销毁!
就是因为这个问题,我在调试代码的时候一直报错“Listen error”。原因就是server
实例在出了try
之后调用了析构函数,而我在析构函数里写了closesocket(this->serverSocket);
,把套接字给关了。
那我想算了,手动new一个对象,手动管理内存吧。结果还是报错!
int main() {
Server* server;
for (int i = 0; i < 3; ++i) {
try {
//cin >> root;
server = new Server(root);
break;
}
catch (const exception& error) {
cout << error.what() << endl;
cout << "Please retype." << endl;
}
}
server->working();
delete server;
return 0;
}
报错:
error C4703: 使用了可能未初始化的本地指针变量“server”