坑爹的一天,坑爹的一结论,析构函数中尽量少释放资源

来源:互联网 发布:服务器php升级 编辑:程序博客网 时间:2024/05/20 09:24

一天的时间用在查找自定义的CServerSocketTCP 和CSocketTCP 两个类,结果因为在两个类中的析构函数中对SOCKET进行了释放,导致了一种结果

例如:一个CSocketTCP  x对象,被复制了一个y。 x和y中同包含一个SOCKET资源,当x的生命周期结束时,x的析构函数调用,释放了该SOCKET资源,

那么y中的SOCKET也被释放了。

结论:析构函数中尽量少释放资源。 释放资源的语句最好放在自定义的函数close中。


CServerSocketTCP.h

————————————————————

#ifndef _CSOCKETTCP_H_
#define _CSOCKETTCP_H_
#include "CSocketTCP.h"
#endif


#ifndef _WINSOCK2_H_
#define _WINSOCK2_H_
#include <winsock2.h>
#endif


class CServerSocketTCP
{
public:
CServerSocketTCP(int port);
~CServerSocketTCP();
CSocketTCP Accept();
void close();
void init();

private:
SOCKET m_serverSocket;
}; 




void CServerSocketTCP::close()
{
closesocket(m_serverSocket);
}


void CServerSocketTCP::init()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 1, 1 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}


if ( LOBYTE( wsaData.wVersion ) != 1 ||
        HIBYTE( wsaData.wVersion ) != 1 ) {
WSACleanup( );
return; 
}
return ;
}


CServerSocketTCP::CServerSocketTCP(int port)
{
init();
m_serverSocket = socket(AF_INET, SOCK_STREAM, 0); // protocol: 选择一个协议,为0,自动选择一个合适的协议

SOCKADDR_IN socketAdress;
socketAdress.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
socketAdress.sin_family = AF_INET;
socketAdress.sin_port = htons(port);

bind(m_serverSocket, (SOCKADDR *) &socketAdress, sizeof(SOCKADDR));

listen(m_serverSocket, 5);
}


CServerSocketTCP::~CServerSocketTCP()
{
// WSACleanup();
//closesocket(m_serverSocket);       //释放资源处
}


CSocketTCP CServerSocketTCP::Accept()
{
SOCKADDR_IN clientAddress;
int len = sizeof(SOCKADDR);
SOCKET clientSocket = accept(m_serverSocket, (SOCKADDR*)&clientAddress, &len);

CSocketTCP cSocket(clientSocket); //SOCKET 资源复制
return cSocket;                   //clientSocket生命周期结束,SOCKET被释放,cSocket中的SOCKET资源同样被释放,cSocket返回值无效了
}



CSocketTCP.h

——————————



#ifndef _WINSOCK2_H_
#define _WINSOCK2_H_
#include <winsock2.h>
#endif






class CSocketTCP
{
public:
CSocketTCP(SOCKET socket);
CSocketTCP(const char * address, int port);
~CSocketTCP();
int write(char * str, int len);
int read(char * str);
void close();
void init();
private:
SOCKET m_socket;
};


void CSocketTCP::init()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 1, 1 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}


if ( LOBYTE( wsaData.wVersion ) != 1 ||
        HIBYTE( wsaData.wVersion ) != 1 ) {
WSACleanup( );
return ; 
}
return ;
}


CSocketTCP::CSocketTCP(SOCKET m_socket)
{
init();
this->m_socket = m_socket;       //SOCKET 资源复制
}


CSocketTCP::CSocketTCP(const char *address, int port)
{
init();
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0); // protocol: 选择一个协议,为0,自动选择一个合适的协议

SOCKADDR_IN socketAdress;
socketAdress.sin_addr.S_un.S_addr = inet_addr(address);
socketAdress.sin_family = AF_INET;
socketAdress.sin_port = htons(port);

int x = connect(serverSocket, (SOCKADDR*) &socketAdress, sizeof(SOCKADDR));
this->m_socket = serverSocket;
}


CSocketTCP::write(char * str, int len)
{
return send(m_socket, str, len, 0);
}


CSocketTCP::read(char * str)
{
return recv(m_socket, str, strlen(str), 0);
}


CSocketTCP::~CSocketTCP()
{

}
void CSocketTCP::close()
{
closesocket(m_socket);
}

原创粉丝点击