![]() |
Read Access Violation
Big problem here.
I have a function WriteBmpPkgFile declared as: :
DWORD WriteBmpPkgFile (const char *szFileName, LPBMPPKGFILE lpBmpPkg)In that function, I have a file write call: :
fwrite(&(lpBmpPkg->dwCount), sizeof(BYTE), sizeof(DWORD), outfile);A BMPPKGFILE is a struct that contains one or more bitmap files. The dwCount member is the number of bitmaps in the package. When I get to that quoted fwrite line, and the program tries to write the dwCount member to outfile, I get a "Read Access Violation" exception and the program crashes. BUT... this only happens when the bitmap is less than 4x4 pixels in size! I allocate memory for the BMPPKGFILE struct when a bitmap is added, and I update the dwCount member, but I NEVER get any allocation errors or read/write access violations when adding a bitmap to a package. Anyone have any idea why this would be happening? Or a suggestion on how to debug it better in MSVC++ Express 2005? Here are the struct definitions, in case they help: :
typedef struct tagBMPPKGFILE {Also, the BMPPKGFILE struct I'm using is created and initialized in this fashion: :
BMPPKGFILE bmppkg; |
Re: Read Access Violation
A breakpoint on the fwrite call would be a start.
Then examine the variables in detail. > this only happens when the bitmap is less than 4x4 pixels in size! Are you taking into account the various ways in which bitmap data is padded/aligned to 4-byte boundaries. |
Re: Read Access Violation
Three issues.
First, what are you trying to output? Your fwrite() line will output sizeof(BYTE)*sizeof(DWORD) characters in a binary format to the file. Depending on what a BYTE is, it may have a size greater than 1. If you are trying to output lpBmpPkg->dwCount then the call would be better off as fwrite(&(lpBmpPkg->dwCount), sizeof(DWORD), 1, outfile);. The second issue is that, if you want to output a data structure using fwrite, it is not a good idea to output structures containing pointers. The pointers, however, they are initialised will probably not contain sense when the struct is read back in. So, doing fwrite(lpBmpPkg, sizeof(BMPPKGFILE), 1, outfile); will output the pointer, but the corresponding fread() call is not guaranteed to give back a useful data structure. The third issue is that there's are a couple of practical rules you're probably ignoring. 1) the real cause of a crash is any code executed at or before the line where the crash occurs. 2) declaring a pointer does not magically create something for that pointer to point at. You must ensure that any pointers are initialised sensibly so they point at something valid. How are these concerns relevant? Your code for initialising bmppkg will set all the characters within bmppkg to zero and, in practice, that will have the effect of setting bmppkg.dwCount to zero and bmppkg.pEntries to a null pointer. If you dereference bmppkg.pEntries (and you are presumably doing that if other code is setting bmppkg.dwCount to a non-zero value) then you are dereferencing a NULL pointer. If I had to guess, you are doing something like this; :
BMPPKGFILE bmppkg; |
Re: Read Access Violation
Quote:
Quote:
This problem is... very odd. The BMPPKGFILE pointer passed to the WriteBmpPkgFile is correct, and the data in the memory it points to is also correct. And fwrite even fails if I do this instead: :
DWORD dwcount = lpBmpPkg->dwCount;And this: :
DWORD dwcount = 0x01; //lpBmpPkg->dwCount;Strange, no? |
Re: Read Access Violation
Grumpy,
My reply to Salem should answer your question about what I'm trying to output... just a DWORD variable. At least, in the line that's causing trouble. As for your comments about misuses of pointers in a struct, the functions I'm using to manage those structures are pretty meticulous. They do properly allocate and reallocate memory for the bitmaps stored in the packages. I've been developing and using them for about a year now, and they are pretty solid. Thanks. |
Re: Read Access Violation
Quote:
|
Re: Read Access Violation
Given your tests in post #4, the only possible culprit would seem to be a problem with outfile
- it isn't open. - it's already been closed. - it's been trashed. FWIW, I would put the *outfile into a watch window as soon as you've opened the file, then compare with what you get when you reach the fwrite call which breaks. If you do see that change "mysteriously", then you can (in some debuggers at least) set up a watch breakpoint which will trap whenever a memory location is read or modified. Sometimes, this is the only way to figure out random memory overrun problems for example. |
Re: Read Access Violation
Quote:
One of the most effective causes of frustration when debugging is to overlook the actual offending code because of a mistaken belief it is "solid". Yes, an error with file I/O can cause a subsequent problem with file I/O. However, the symptom you are describing is not a typical I/O error: it is a sign some part of your program is accessing memory it shouldn't. Technically, that can happen in an I/O operation (eg a fwrite(&(lpBmpPkg->dwCount), sizeof(BYTE), sizeof(DWORD), outfile); could do a buffer overrun, depending on the value of sizeof(BYTE)), but that doesn't mean the problem is I/O related. |
Re: Read Access Violation
Right on, Grumpy.
I was operating under the assumption that an exception would be thrown immediately if I wrote more data to an allocated buffer than it could hold. I was adding a bitmap to the package directly before writing the package to disk. In the add function, I was using the biSize member of the BITMAPINFOHEADER structure, instead of biSizeImage. So, when there were fewer than sizeof(BITMAPINFOHEADER) bytes in the bit field, the code failed. Makes sense. Still, why wouldn't it throw an exception when I copied too many bytes from the bitmap file that was already in memory? And why wouldn't it throw an exception when I wrote more data than the memory space could handle? Thanks for the push, Grumpy. I likely would have been spinning my wheels for days on this one. And thank you Salem, for your assistance. It is appreciated. |
Re: Read Access Violation
Well you could use a tool like Electric Fence which allocates each block of memory in such a way that if you step off the end at all, then you'll get an exception.
|
| All times are GMT -5. The time now is 3:42 AM. |
Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC