|
Archives
D Programming
DD.gnu digitalmars.D digitalmars.D.bugs digitalmars.D.dtl digitalmars.D.dwt digitalmars.D.announce digitalmars.D.learn digitalmars.D.debugger C/C++ Programming
c++c++.announce c++.atl c++.beta c++.chat c++.command-line c++.dos c++.dos.16-bits c++.dos.32-bits c++.idde c++.mfc c++.rtl c++.stl c++.stl.hp c++.stl.port c++.stl.sgi c++.stlsoft c++.windows c++.windows.16-bits c++.windows.32-bits c++.wxwindows digitalmars.empire digitalmars.DMDScript |
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.0 Nov 23 2004
|