頻繁通過win32api的createfile函式開啟檔案控制代碼導致記憶體洩漏
阿新 • • 發佈:2019-02-19
1、通過win32的createfile、writefile函式開啟寫入檔案
因為寫檔案是開執行緒寫的,故寫了個迴圈用於等待獲取檔案控制代碼,當檔案被佔用時,就會一直迴圈等等。獲取到檔案控制代碼後,再呼叫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); }
因為程式有記憶體洩漏問題,即某些記憶體沒有釋放掉,故跟蹤程式碼發現在迴圈createfile這個函式中會存在記憶體洩漏,應該是控制代碼洩漏。
正常開啟檔案控制代碼後,通過closehandle函式應該能釋放掉檔案控制代碼以及佔用的記憶體。但是測試結果就是不行。
2、最後實在找不到原因,懷疑就是win32自身的問題,迫不得已換一種寫法用ofstream來寫入檔案,需要引用標頭檔案#include <fstream>
建議對檔案進行讀寫操作,儘量使用ofstream、ifstream等c++的庫。儘量windows作業系統提供的createfile函式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(); }