c++.windows.32-bits - My use of CMemFile not working in release mode
I am using VC++ 6.0 and have a multi-threaded application (exe & multiple DLLs) which seem to be having a CMemFile object getting clobbered when running in release mode. It does not happen in debug mode. When running in the debugger, the calling thread that builds the memory file reports: GetPosition = 0 GetLength = 228 ptr to memfile = aa2238 the method GetTextLineNOF is passed a ptr to CMemFile and reports: GetPosition = 0 GetLength = 228 ptr to memfile = aa2238 Which agrees as expected. ==== However when running in RELEASE mode: the calling thread that builds the memory file reports: GetPosition = 0 GetLength = 228 ptr to memfile = 7ccd10 the method GetTextLineNOF is passed a ptr to CMemFile and reports: GetPosition = 8cf829 WHICH IS WRONG! GetLength = IT appears to be blowing up on this call to GetLength with access violation ptr to memfile = 7ccd10 Here are two code snippets. Note that each is in its own DLL! Input file can be any random file even 5 lines long created in notepad. // ZZZ.cpp : Defines the entry point for the DLL application. // #include "stdafx.h" #include "TWC.h" #include <afxinet.h> #include "atlbase.h" #include "generator.h" #include <wininet.h> #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif /***************************************************************/ // Define Constants /***************************************************************/ // Boolean Constants #define SUCCESS 1 // Boolean TRUE #define NOTSUCCESSFUL 0 // Boolean FALSE // Registry Constants #define REGISTRYBASE HKEY_LOCAL_MACHINE #define YYYGENPATH "SYSTEM\\\\CurrentControlSet\\\\Services\\\\xyz" #define CHECKTIME 60000 #define TEXTLINE_SIZE 256 // For buffers receiving GetTextLineNOF output /***************************************************************/ // Function prototypes. /***************************************************************/ BOOL SetPageValues(CMemFile* brMemFile); CString PullField(CString csLine, int nField, char cDelimiter); CString MakeProperName(CString csOld); CString GetFullDayName(CString csShortDay); char * GetTextLine(CMemFile* file, char *pchResult); char * GetTextLineNOF(CMemFile* file, char *pchResult, long maxlen); BOOL UnZipFile(LPCTSTR ZipFileName); /***************************************************************/ // Global Declarations /***************************************************************/ // Common Globals CString Temp = _T(""); CString TemplatePath = _T(""); CString TempPath = _T(""); CString LogPath = _T(""); // Specific Globals CString Logging = _T(""); CString OutputFileName = _T(""); CString RunTimes = _T(""); CString TemplateFileName = _T(""); CString PageDataPath = _T(""); CString City = _T(""); CString csConfigPath = _T(""); int OutputLocationNumber = 0; CString *OutputLocations = NULL; int CityLocationNumber = 0; CString *CityLocations = NULL; CTime LastRun = CTime(0); ARGLIST Events = {0}; char ClientName[255] = ""; /***************************************************************/ // Function Declarations /***************************************************************/ void DllExport __cdecl PROBLEMThread(ARGLIST &threadParm) { CString csError = _T(""); char szLine[1024] = ""; CString ZZZConfigPath = _T(""); BOOL FTPGrabFile = FALSE; char TextLineBuf[TEXTLINE_SIZE] = ""; //placeholder for GetTextLineNOF //DebugBreak(); try { // Get the Computer Name GetComputerName(ClientName); MyOutputDebugString(1, "PROBLEM : PROBLEM Thread Starting \n"); Events = threadParm; MyOutputErrorString(1, "6100,xxx, %s, PROBLEM: Starting PROBLEM Page Generation\n", ClientName); char szFilePath[_MAX_PATH] = ""; char * ModuleName = NULL; HMODULE ModuleHandle = NULL; ModuleName = "ZZZ.dll"; // Get a handle to the DLL Library. ModuleHandle = GetModuleHandle(ModuleName); // Retrieve the path to the DLL. GetModuleFileName(ModuleHandle, szFilePath, sizeof(szFilePath)); CString csDLLPath = _T(""); csDLLPath = szFilePath; // Strip the path to the DLL off in order to figure out the path to the config file. csConfigPath = csDLLPath.Left(csDLLPath.ReverseFind('\\')); // Build the path to the config file. ZZZConfigPath.Format("%s\\ZZZ.cfg", csConfigPath); // Check to see if I should run every CHECKTIME do { FTPGrabFile = FALSE; MyOutputDebugString(1, "PROBLEM : Checking Page RunTimes for update \n"); MyOutputDebugString(1, "PROBLEM : Opening %s for reading into memory file \n",ZZZConfigPath); // Open the ZZZ Configuration file for Reading. CStdioFile cfInfile(ZZZConfigPath, CFile::modeRead | CFile::typeText | CFile::shareDenyNone); // Create a Memory File which will contain the ZZZ config file CMemFile* brMemFile = new CMemFile; // Read from the ZZZ Configuration File while (cfInfile.ReadString(szLine, 1024) != NULL) { // Write to the Memory File brMemFile->Write(szLine, strlen(szLine)); } // Close the ZZZ Configuration File cfInfile.Close(); // Seek to the Beginning of the Memory File brMemFile->SeekToBegin(); //for debugging write out the CMemFile statistics DWORD dwPos = brMemFile->GetPosition(); MyOutputDebugString(1, "PROBLEM : CMemFile position = %x\n",dwPos); DWORD dwLen = brMemFile->GetLength(); MyOutputDebugString(1, "PROBLEM : CMemFile length = %x\n",dwLen); MyOutputDebugString(1, "PROBLEM : ptr to CMemFile = %x\n", brMemFile); // Set up the Global Values MyOutputDebugString(1, "PROBLEM : Making first call to GetTextLineNOF\n"); TemplatePath = GetTextLineNOF(brMemFile, TextLineBuf, sizeof(TextLineBuf)); BLAHBLAHBLAH ---- And here is the method being called: char * GetTextLineNOF(CMemFile* file, char *pchResult, long maxlen) { // PURPOSE: Read a single line of text from the memory file (which usually contains a // *.cfg file). Store the line into the array pointed to by pchResult. It is // the responsibility of the caller to properly set maxlen to the size of the // array pointed to by pchResult so that buffer overflows are prevented. // Any comments in the memory file (indicated with a leading ~) will be ignored // and not returned by this method. Lines in the memory file are terminated // with CRLF (ie. Hex 0D0A) but when read in only 0A is returned by // file->Read(&iChar, 1);. // NOTE: There are 6 formats of valid lines in the memory file as follows: // 1. ~Comment // 2. leading blanks + ~Comment // 3. data line starting in column 0 // 4. leading blanks + data line // 5. leading blanks + data line + ~comment // 6. data line starting in column 0 + ~Comment // // RETURNS: String with leading blanks and trailing comments removed. // Lines that only contain CRLF will be ignored. // Lines containing only blanks will be ignored. char iChar = '\0'; char skipChar = '\0';// throw away this char because buffer is full int iColumn = 0; // number of chars copied to pchResult char *pchTemp; // use this to march across the array 1 char at a time MyOutputDebugString (1, "Inside GetTextLineNOF \n"); //for debugging MyOutputDebugString(1, "PROBLEM : ptr to CMemFile = %x\n", file); MyOutputDebugString (1, "GetTextLineNOF - just after accessing file \n"); DWORD dwPos = file->GetPosition(); MyOutputDebugString (1, "GetTextLineNOF - just after calling GetPosition \n"); MyOutputDebugString (1, "GetTextLineNOF: CMemFile pos = %x \n", dwPos); DWORD dwLen = file->GetLength(); MyOutputDebugString (1, "GetTextLineNOF - just after calling GetLength \n"); MyOutputDebugString (1, "GetTextLineNOF: CMemFile len = %x \n", dwLen); pchTemp = pchResult; MyOutputDebugString (1, "after first line GetTextLineNOF \n"); try { // loop, until we have something to return (iColumn>0) while ( TRUE ) { BOOL IgnoreThisChar = FALSE; BOOL endOfFile = FALSE; //whether we have read entire memory file // Loop until we hit a CR (decimal 10) or the end of the file if ( file->GetPosition() >= file->GetLength() ) endOfFile = TRUE; if ( !endOfFile ) { do { file->Read(&iChar, 1); // Store the character read from memfile UNLESS a comment or leading blank if ( iChar == '~' ) { // set to ignore everything after the comment flag IgnoreThisChar = TRUE; //if comment is on a data line, then terminate string here if (iColumn > 0) { MyOutputDebugString (1, "GetTextLineNOF Terminating string"); *(pchTemp+iColumn) = '\0'; iColumn++; } } else if ((iChar == ' ') && (iColumn == 0)) { continue; //skips over leading blanks } else if (!IgnoreThisChar) //valid char to return or CRLF { // add the character to the return value if not a comment or leading blank if ( iChar != 10 ) { // check for buffer overflow // the minus 1 is to allow for nul stored at bottom of this method if (iColumn >= maxlen - 1) { // if this will overflow - do not store char AND *(pchTemp+iColumn) = '\0'; iColumn++; // - write error msg AND // - skip over the end of the line AND do { file->Read(&skipChar, 1); if ( file->GetPosition() >= file->GetLength() ) endOfFile = TRUE; } while (!endOfFile && skipChar != 10 ); // try to return the next line } else // store the char { *(pchTemp+iColumn) = iChar; iColumn++; //MyOutputDebugString (1, "GetTextLineNOF Assigning char = %c\n",iChar); } } else // iChar == 10 *(pchTemp+iColumn) = '\0'; // hit LF in mem file so terminate string } //END else the character was stored for return if ( file->GetPosition() >= file->GetLength() ) endOfFile = TRUE; // MyOutputDebugString(4, "iChar = %c\n", iChar); } while (!endOfFile && iChar != 10 && skipChar !=10); } //END if (!endOfFile) if (endOfFile) { *(pchTemp+iColumn) = '\0'; iColumn++; } // check the return value, if it is not empty then return everything // before we hit the comment flag. Else continue to loop, until we have // something to return if (iColumn > 0) { break; // MyOutputDebugString(4, "IgnoreThisChar = FALSE\n"); } //else // MyOutputDebugString(4, "IgnoreThisChar = TRUE\n"); } //END while TRUE //MyOutputDebugString(4, "%s\n", szLine); } //END try block catch ( CException* e ) { TCHAR szCause[255] = _T(""); e->GetErrorMessage(szCause, 255); //MyOutputDebugString (1, "xxx: %s\n", szCause ); e->Delete(); exit(0); } MyOutputDebugString (1, "GetTextLineNOF Returning string %s \n",pchResult); return pchResult; } ======= Any ideas on how to solve the access violation problem in release mode??? Thanks! malhenry
Oct 12 2004
"malhenry" <malhenry_member pathlink.com> wrote in message news:ckhdm7$1d8t$1 digitaldaemon.com...I am using VC++ 6.0There's the problem! You should be using Digital Mars C++! <g>
Nov 23 2004