首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

这段代码能导致内存一直增加,求解

2013-12-04 
这段代码会导致内存一直增加,求解代码如下,是一段Socket代码WSADATA infoWSAStartup(MAKEWORD(2,0), &inf

这段代码会导致内存一直增加,求解
代码如下,是一段Socket代码


        WSADATA info;
WSAStartup(MAKEWORD(2,0), &info);
s_ = socket(AF_INET,SOCK_STREAM,0);
int iTimerout = 1000*10;
setsockopt(s_,SOL_SOCKET,SO_RCVTIMEO,(const char*)&iTimerout,sizeof(int));
        closesocket(s_);
        WSACleanup();    //这里有关闭这调用就会导致内存一直增加


通过测试,效果是这样的,如果调用WSACleanup(),内存则会一直增加,不调用就没事,我的理解是WSACleanup()调用之后,关闭线程里所有的操作,而Socket里的资源一直没有得到释放,而如果不调用的话,socket就有足够的时间去释放占用的资源,是不是这样呢,如果为了解决这个问题,不调用WSACleanup我想应该是有问题的,求解! C++ SOCKET API 内存泄露 WSACleanup
[解决办法]
why not:


        WSADATA info;
WSAStartup(MAKEWORD(2,0), &info);
while(1)
{
s_ = socket(AF_INET,SOCK_STREAM,0);
int iTimerout = 1000*10;
setsockopt(s_,SOL_SOCKET,SO_RCVTIMEO,(const char*)&iTimerout,sizeof(int));
//...do something
        closesocket(s_);


}
        WSACleanup();    //这里有关闭这调用就会导致内存一直增加

[解决办法]
在closesocket前加shutdown试试;或者观察时间长一些,是不是内存占用到达一定值以后就不在增加。
[解决办法]
WSACleanup
The Windows Sockets WSACleanup function terminates use of the WS2_32.DLL.

int  WSACleanup (void);
Remarks
An application or DLL is required to perform a successful WSAStartup call before it can use Windows Sockets services. When it has completed the use of Windows Sockets, the application or DLL must call WSACleanup to deregister itself from a Windows Sockets implementation and allow the implementation to free any resources allocated on behalf of the application or DLL. Any pending blocking or asynchronous calls issued by any thread in this process are canceled without posting any notification messages or without signaling any event objects. Any pending overlapped send and receive operations (WSASend/WSASendTo/WSARecv/WSARecvFrom with an overlapped socket) issued by any thread in this process are also canceled without setting the event object or invoking the completion routine, if specified. In this case, the pending overlapped operations fail with the error status WSA_OPERATION_ABORTED. 

Sockets that were open when WSACleanup was called are reset and automatically deallocated as if closesocket were called; sockets that have been closed with closesocket but that still have pending data to be sent can be affected—the pending data can be lost if the WS2_32.DLL is unloaded from memory as the application exits. To insure that all pending data is sent, an application should use shutdown to close the connection, then wait until the close completes before calling closesocket and WSACleanup. All resources and internal state, such as queued un-posted messages, must be deallocated so as to be available to the next user.

There must be a call to WSACleanup for every successful call to WSAStartup made by a task. Only the final WSACleanup for that task does the actual cleanup; the preceding calls simply decrement an internal reference count in the WS2_32.DLL.

Return Values
The return value is zero if the operation was successful. Otherwise, the value SOCKET_ERROR is returned, and a specific error number can be retrieved by calling WSAGetLastError.



Attempting to call WSACleanup from within a blocking hook and then failing to check the return code is a common programming error in Windows Socket 1.1 applications. If an application needs to quit while a blocking call is outstanding, the application must first cancel the blocking call with WSACancelBlockingCall then issue the WSACleanup call once control has been returned to the application.

In a multithreaded environment, WSACleanup terminates Windows Sockets operations for all threads.

Error Codes
WSANOTINITIALISED A successful WSAStartup must occur before using this function. 
WSAENETDOWN The network subsystem has failed. 
WSAEINPROGRESS A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. 


QuickInfo
  Windows NT: Yes
  Windows: Yes
  Windows CE: Use version 1.0 and later.
  Header: Declared in winsock2.h.
  Import Library: Link with ws2_32.lib.

See Also
closesocket, shutdown, WSAStartup 

 

[解决办法]
我记得是WSAStartup及WSACleanup每个应用只需调用一次。试试把这两个函数放在main函数的开头与末尾。
[解决办法]


class classA
{
public:
classA();
~classA();
void Start();
private:
SOCKET s_;
};

void classA::Start()
{
WSADATA info;
WSAStartup(MAKEWORD(2,0), &info);
cout << "开始..." << endl;
}
classA::classA()
{
Start();
s_ = socket(AF_INET,SOCK_STREAM,0);
int iTimerout = 1000*10;
setsockopt(s_,SOL_SOCKET,SO_RCVTIMEO,(const char*)&iTimerout,sizeof(int));
cout << "构造..." << endl;

}
classA::~classA()
{
closesocket(s_);
WSACleanup();    //这里有关闭这调用就会导致内存一直增加
cout << "虚构..." << endl;
}
//这上面的代码是封装成一个库的,
void main()
{
    classA classa;//放在这里啊!!!!
    while(1)   //while这样写的目的是代码里会有很多地方会调用到 classA classa做的一个测试
    {
        
        //其它的逻辑处理
        //...
        ////////////////
    }  
    //难道我要在程序退出的时候再调用WSACleanup?(也就是库的外面?)
}

[解决办法]
 To insure that all pending data is sent, an application should use shutdown to close the connection, then wait until the close completes before calling closesocket and WSACleanup. All resources and internal state, such as queued un-posted messages, must be deallocated so as to be available to the next user.
[解决办法]
引用:

class classA
{
public:
classA();
~classA();
void Start();
private:
SOCKET s_;
};

void classA::Start()
{
WSADATA info;
WSAStartup(MAKEWORD(2,0), &info);
cout << "开始..." << endl;
}
classA::classA()
{
Start();
s_ = socket(AF_INET,SOCK_STREAM,0);
int iTimerout = 1000*10;
setsockopt(s_,SOL_SOCKET,SO_RCVTIMEO,(const char*)&iTimerout,sizeof(int));
cout << "构造..." << endl;

}
classA::~classA()
{
closesocket(s_);
WSACleanup();    //这里有关闭这调用就会导致内存一直增加
cout << "虚构..." << endl;
}
//这上面的代码是封装成一个库的,
void main()
{
    classA classa;//放在这里啊!!!!
    while(1)   //while这样写的目的是代码里会有很多地方会调用到 classA classa做的一个测试
    {
        
        //其它的逻辑处理
        //...
        ////////////////
    }  
    //难道我要在程序退出的时候再调用WSACleanup?(也就是库的外面?)
}


不是这样啊!只把那两个函数拿出来即可。大概这样:

int main()
{
   ...
   WSAStartup(...);

   // 这里你原来的代码。
   ...

   WSACleanup();



 return 0;
}


[解决办法]
楼主你的设计是有问题的, 如果你同时构造了两个classA的实例,就会同时WSAStartup两次,然后你析构其中一个,是不是会出现另一个也无法使用的问题啊?

另外测试内存增加这个事时有必要使用release版本,并且不要在VS或其它IDE、调试器中运行。如果内存依然增加, 那恭喜你为MS找到一个BUG。
[解决办法]
引用:
楼主你的设计是有问题的, 如果你同时构造了两个classA的实例,就会同时WSAStartup两次,然后你析构其中一个,是不是会出现另一个也无法使用的问题啊?

另外测试内存增加这个事时有必要使用release版本,并且不要在VS或其它IDE、调试器中运行。如果内存依然增加, 那恭喜你为MS找到一个BUG。


+1
[解决办法]
引用:
Quote: 引用:


class classA
{
public:
classA();
~classA();
void Start();
private:
SOCKET s_;
};

void classA::Start()
{
WSADATA info;
WSAStartup(MAKEWORD(2,0), &info);
cout << "开始..." << endl;
}
classA::classA()
{
Start();
s_ = socket(AF_INET,SOCK_STREAM,0);
int iTimerout = 1000*10;
setsockopt(s_,SOL_SOCKET,SO_RCVTIMEO,(const char*)&iTimerout,sizeof(int));
cout << "构造..." << endl;

}
classA::~classA()
{
closesocket(s_);
WSACleanup();    //这里有关闭这调用就会导致内存一直增加
cout << "虚构..." << endl;
}
//这上面的代码是封装成一个库的,
void main()
{
    classA classa;//放在这里啊!!!!
    while(1)   //while这样写的目的是代码里会有很多地方会调用到 classA classa做的一个测试
    {
        
        //其它的逻辑处理
        //...
        ////////////////
    }  
    //难道我要在程序退出的时候再调用WSACleanup?(也就是库的外面?)
}


不是这样啊!只把那两个函数拿出来即可。大概这样:

int main()
{
   ...
   WSAStartup(...);

   // 这里你原来的代码。
   ...

   WSACleanup();

 return 0;
}

+1
[解决办法]
这个真的是结构的问题,设计的时候2个函数应该只有一次调用即可,初始化环境的函数,需要看源码

热点排行