您的位置:首页 > 其它

频繁通过win32api的createfile函数打开文件句柄导致内存泄漏

2017-04-12 16:58 351 查看
1、通过win32的createfile、writefile函数打开写入文件

void WriteLogThread(void* lpParameter)
{
LPLogData pData = (LPLogData)lpParameter;
string logContent=pData->logContent;
string logType=pData->logType;
//释放传参所分配的堆内存
//HeapFree(GetProcessHeap(), 0, pData);
delete pData;

string strPath="C:\\HttpServerLog";
WIN32_FIND_DATAA wfd;
HANDLE hFind = FindFirstFileA(strPath.c_str(),&wfd);
if (hFind == INVALID_HANDLE_VALUE)
{
//目录不存在
CreateDirectoryA(strPath.c_str(), NULL);
}
FindClose(hFind);

HANDLE hFile;
string fileName="C:\\HttpServerLog\\HttpServerLog"+GetData()+".html";
do
{
hFile = CreateFileA(fileName.c_str(), //创建文件的名称。
GENERIC_WRITE|GENERIC_READ, // 写和读文件。
0, // 不共享读写。
NULL, // 缺省安全属性。
OPEN_ALWAYS, // 总打开文件,如不存在,则创建
FILE_ATTRIBUTE_NORMAL, // 一般的文件。
NULL); // 模板文件为空。

//文件被占用时
if(hFile == INVALID_HANDLE_VALUE)
{
Sleep(500);//等待500毫秒
}
} while (hFile == INVALID_HANDLE_VALUE);

//设置写入位置
LONG lDistance = 0;
SetFilePointer(hFile, lDistance, NULL, FILE_END);

//往文件里写数据
string str= "";

if(logType=="Error")
{
str= "<hr>\r\n<h5 style='color:red'>["+logType+"]"+GetDataTime()+"</h5>\r\n<h6 style='color:red'>"+logContent+"</h6>\r\n";
}
else
{
str= "<hr>\r\n<h5 style='color:blue'>["+logType+"]"+GetDataTime()+"</h5>\r\n<h6 style='color:blue'>"+logContent+"</h6>\r\n";
}
int len = lstrlenA(str.c_str());
DWORD dwWritenSize = 0;
BOOL bRet = WriteFile(hFile,str.c_str(),len,&dwWritenSize,NULL);

//先把写文件缓冲区的数据强制写入磁盘。
FlushFileBuffers(hFile);
//关闭文件
CloseHandle(hFile);
}因为写文件是开线程写的,故写了个循环用于等待获取文件句柄,当文件被占用时,就会一直循环等等。获取到文件句柄后,再调用writefile执行文件写入。
因为程序有内存泄漏问题,即某些内存没有释放掉,故跟踪代码发现在循环createfile这个函数中会存在内存泄漏,应该是句柄泄漏。

正常打开文件句柄后,通过closehandle函数应该能释放掉文件句柄以及占用的内存。但是测试结果就是不行。

2、最后实在找不到原因,怀疑就是win32自身的问题,迫不得已换一种写法用ofstream来写入文件,需要引用头文件#include <fstream>

void WriteLogThread(void* lpParameter)
{
LPLogData pData = (LPLogData)lpParameter;
string logContent=pData->logContent;
string logType=pData->logType;
//释放传参所分配的堆内存
//int a =HeapFree(GetProcessHeap(), 0, pData);
delete pData;

string strPath="C:\\HttpServerLog";
WIN32_FIND_DATAA wfd;
HANDLE hFind = FindFirstFileA(strPath.c_str(),&wfd);
if (hFind == INVALID_HANDLE_VALUE)
{
//目录不存在
CreateDirectoryA(strPath.c_str(), NULL);
}
FindClose(hFind);

string fileName="C:\\HttpServerLog\\HttpServerLog"+GetData()+".html";

//利用ofstream进行写操作
//输出流,把流输出到存储设备
//ios::in 为输入(读)而打开文件
//ios::out 为输出(写)而打开文件
//ios::ate 初始位置:文件尾
//ios::app 所有输出附加在文件末尾
//ios::trunc 如果文件已存在则先删除该文件
//ios::binary 二进制方式
ofstream out;
out.open(fileName.c_str(),ios::out|ios::app);
while(!out.is_open())
{
Sleep(5000);
out.open(fileName.c_str(),ios::out);
}

string str= "";
if(logType=="Error")
{
str= "<hr>\r\n<h5 style='color:red'>["+logType+"]"+GetDataTime()+"</h5>\r\n<h6 style='color:red'>"+logContent+"</h6>\r\n";
}
else
{
str= "<hr>\r\n<h5 style='color:blue'>["+logType+"]"+GetDataTime()+"</h5>\r\n<h6 style='color:blue'>"+logContent+"</h6>\r\n";
}

out<<str.c_str();
out.close();
}建议对文件进行读写操作,尽量使用ofstream、ifstream等c++的库。尽量windows操作系统提供的createfile函数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: