Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

InternetFindNextFile() is crashing! 1

Status
Not open for further replies.

cpjust

Programmer
Sep 23, 2003
2,132
0
0
US
Hi, since I couldn't get the MFC stuff working in VC++ 2005 Express Edition, I decided to try using the WinInet API calls... I can get the name of the first FTP file by calling FtpFindFirstFile(), but after I call InternetFindNextFile() and do a few more lines of code my program gets "Unhandled exception at 0xbaadf00d in TestHarness.exe: 0xC0000005: Access violation reading location 0xbaadf00d."

Here is some of the relevent code:
Code:
AutoCloseHandle hInet( InternetOpen( _T( "An FTP program" ), 
										 INTERNET_OPEN_TYPE_DIRECT,
										 NULL, NULL,
										 INTERNET_FLAG_ASYNC ) );

	if ( hInet == NULL )
	{
		throw runtime_error( "InternetOpen() failed!" );
	}

	AutoCloseHandle hFtp( InternetConnect( hInet.Get(),
										   _T( "something.com" ),
										   INTERNET_DEFAULT_FTP_PORT,
										   NULL, NULL,	// Default username & password.
										   INTERNET_SERVICE_FTP,
										   INTERNET_FLAG_PASSIVE,
										   NULL ) );

	if ( hFtp == NULL )
	{
		throw runtime_error( "InternetConnect() failed!" );
	}

	// Now get a list of all the files in that directory.
	vector<const string> foundFiles;
	WIN32_FIND_DATA findData;
	AutoCloseHandle hFindFile( FtpFindFirstFile( hFtp.Get(),
												 NULL,
												 &findData,
												 INTERNET_FLAG_RELOAD,
												 NULL ) );

	if ( hFindFile != NULL )
	{
		const string file( WCharToString( findData.cFileName ) );
		foundFiles.push_back( file );

		while ( InternetFindNextFile( hFindFile.Get(), &findData ) != FALSE )
		{
			const string file( WCharToString( findData.cFileName ) );
			foundFiles.push_back( file );
		}

		cout << endl << "Last Error was: " << ErrorString( GetLastError() ) << endl;

		if ( GetLastError() != ERROR_NO_MORE_FILES )
		{
			throw runtime_error( "InternetFindNextFile() failed!" );
		}
	}
What it's doing is skiping the while loop completely because InternetFindNextFile() fails and sets the LastError to 997 "Overlapped I/O operation is in progress."
Then when it gets to the cout line I get the exception (although it's not the cout that causes it. It's definitely a delayed side effect of the InternetFindNextFile() call).

What in the world is going on???
 
ArkM, xwb, Salem, anyone...?
I've run out of ideas to try.
 
An interesting read on 0xbaadf00d
Looks like something took some of that memory and used it as a pointer - not good.

> vector<const string> foundFiles;
When I try a const string in g++, I get loads of abuse from the compiler, a lot of which seem to relate to being unable to instantiate a suitable allocator.
Apart from trying without const, I have nothing.

--
 
Wow, I never thought of searching for the hex address... :) That IS a pretty interesting site.

I had similar problems with the const strings using VC++ 6.0, but for some reason 2005 doesn't complain. I removed the consts just in case, but that didn't help.

When I step through the debugger I can't see that 0xbaadf00d address anywhere, but as soon as I crash I see those addresses in the ECX and EIP registers:
Code:
EAX = 00000000 EBX = 00000000 ECX = BAADF00D EDX = 7C9037D8 ESI = 00000000 
EDI = 00000000 EIP = BAADF00D ESP = 00031180 EBP = 000311A0 EFL = 00000246
I've changed my while loop to this:
Code:
do
{
	while ( InternetFindNextFile( hFindFile.Get(), &findData ) != FALSE )
	{
		string file( WCharToString( findData.cFileName ) );
		foundFiles.push_back( file );
	}

	Sleep( 500 );
}
while ( GetLastError() != ERROR_NO_MORE_FILES );
but it again, immediately fails from InternetFindNextFile() and crashes when I run the Sleep() function. I've tried using different things there like cout and it looks like it doesn't matter what I have there, just as long as it takes over a certain amount of time to run. If I cout a very short string, I doesn't crash, but if I cout a longer string, it crashes.

Another strange thing is that if I step through the assembly code of the Sleep() call, I crash as soon as I step OVER a call instruction, but if I step INTO that same call instruction and continue all the way to the ret instruction, I don't crash.
 
> EIP = BAADF00D
Well this is a really bad sign - your code took a flyer at uninitialised memory.

I'm thinking something like
- mis-matched calling conventions trashing your stack
- insufficient space for local variables

> just as long as it takes over a certain amount of time to run.
Well the only thing I can think of here is that something else happens if the execution time is long enough to cause the OS to schedule something else to happen in the meantime.
But I've no idea why that should matter, nor why single stepping does work.

> ESP = 00031180 EBP = 000311A0
Are these consistent with the ESP/EBP at the point you call InternetFindNextFile for the first time. I notice many other registers are zero, which seems a tad unusual in itself.

What is the initial ESP at main/winmain?
How far away from the initial ESP is the current ESP - are you running very close to the stack space limits say?

Are you running threads in your code, perhaps a separate thread has some memory in the proximity of this stack, and is just overstepping it's own memory and taking the stack of this thread with it.

Given that 0xbaadf00d is only written by HeapAlloc(), it seems to me that the heap thinks part of the stack is actually part of the heap. Freeing a local variable in some other function might just make that happen, though I would have hoped it would spot you trying to free something which was never allocated.

--
 
Hmm... All that stepping through assembly code, and all I had to do to fix the problem was change my call to InternetOpen() to use the WININET_API_FLAG_SYNC flag instead of INTERNET_FLAG_ASYNC.

I think it was trying to make a callback before, and since I didn't set a callback function, it did something very baad. :)

Thanks for the help though. At least I got a little more experience with assembly & watching the registers...
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top