什么是 CInternetSession 的必要清理

What is necessary cleanup for CInternetSession

CInternetSession::Close() 的 MSDN 文档只说

Call this member function when your application has finished using the CInternetSession object.

MSDN for CInternetSession::Close

对于由 CInternetSession::GetHttpConnection() 编辑的 CHttpConnection 对象和由 CHttpConnection::OpenRequest() 编辑的 CHttpFile 对象 return,执行这些对象必须手动关闭和删除?

我在 MSDN 上找不到 CHttpConnection::Close() 的文档,CHttpFileCInternetFile 继承了它的 Close() 方法;其文档同样没有帮助:

Closes a CInternetFile and frees any of its resources.

(sorry, I can't have three links)

我的直觉假设是,因为 CInternetSession::GetHttpConnection()CHttpConnection::OpenRequest() return 指针,并且因为 CHttpConnection 的 MSDN 说

You never create a CHttpConnection object directly; rather, call CInternetSession::GetHttpConnection, which creates the CHttpConnection object and returns a pointer to it.

(sorry, I can't have three links)

CInternetSession 在内部存储对它生成的 CHttpConnection 的引用,并在调用 CInternetSession::Close() 时清除该对象。这是由 this MSDN article 支持的,它没有提到对连接对象的任何清理,并指出

Dispose of the CInternetSession object --> Automatically cleans up open file handles and connections.

简短的问题

有这个必要吗:

CInternetSession session(...);
CHttpConnection * connection = session.GetHttpConnection(...);
CHttpFile * file = connection->OpenRequest(...);

... Do stuff ...

file->Close();
delete file;

connection->Close();
delete connection;

session.Close();

或者这样做是否足够:

CInternetSession session(...);
CHttpConnection * connection = session.GetHttpConnection(...);
CHttpFile * file = connection->OpenRequest(...);

... Do stuff ...

session.Close();

元问题

如果---根据库的文档---不清楚清理资源的责任在哪里,检测资源泄漏的可能方法是什么?我知道 Valgrind 可用于内存泄漏,但文件句柄和其他可能被占用的资源呢?

简短的回答是您不必调用 Close(),它由 MFC 析构函数完成。理想情况下,析构函数应该进行所有必要的清理。

MFC 类 如您所述,文档记录不完整。 WinINet 函数有更好的文档:

MSDN WinINet functions

它说,例如,::InternetOpen 句柄必须用 InternetCloseHandle 关闭。我们可以查看 MFC 类 的定义并进行比较:

C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\atlmfc\src\mfc\inet.cpp

CInternetSession(){
    ::InternetOpen //WinINet
    ...
}

CInternetSession::Close(){
    ::InternetCloseHandle //WinINet
    ...
}

CInternetSession::~CInternetSession(){
    Close();
}

所以我们不需要调用 internetSession.Close() 因为它是由析构函数自动完成的。打电话给它不会有什么坏处。我想如果 CInternetSession 是在堆上声明的,那么我们可能需要 Close() 因为在调用析构函数之前可能需要一些时间。

在另一个示例中,我们也不必调用 Close,但这并没有什么坏处。

CHttpFile * file = connection->OpenRequest(...);
file->Close();//I think this is okay but not necessary because we "delete file" in next line
delete file;//calls Close(); and other necessary cleanups

简短版本:

CInternetSession session(...);
CHttpConnection *connection = session.GetHttpConnection(...);
CHttpFile *file = connection->OpenRequest(...);
//... Do stuff ...
delete file;//don't skip
delete connection;//don't skip
//session.Close();//you can skip, this gets called when we exist the function

对了,把断点放在CInternetSession obj上,然后单步执行,应该也会带你到MFC文件..\VC\atlmfc\src\mfc\inet.cpp