![]() |
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
|
|
#1 |
|
Programmer
Join Date: Feb 2006
Location: Ohio
Posts: 93
Rep Power: 3
![]() |
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 {
DWORD dwCount; // How many images are in this file?
BMPPKGENTRY *pEntries; // pEntries[0..(nCount-1)] = &BMPPKGENTRY
} BMPPKGFILE, *LPBMPPKGFILE;
typedef struct tagBMPPKGENTRY {
DWORD dwEntrySize; // size of this entire entry, in bytes
DWORD dwNameSize; // size of the szName field, in bytes (+\0)
DWORD dwFileSize; // size of the bitmap data, in bytes
char *szName; // pointer to the name
BYTE *pRawBmpFile; // pointer to the raw bitmap file data
} BMPPKGENTRY, *LPBMPPKGENTRY;Also, the BMPPKGFILE struct I'm using is created and initialized in this fashion: BMPPKGFILE bmppkg; ZeroMemory(&bmppkg, sizeof(BMPPKGFILE));
__________________
Neeley.org |
|
|
|
|
|
#2 |
|
Programmer
Join Date: Nov 2007
Posts: 33
Rep Power: 0
![]() |
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.
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut. |
|
|
|
|
|
#3 | ||
|
Programmer
Join Date: Feb 2006
Location: Ohio
Posts: 93
Rep Power: 3
![]() |
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;
// write the dwCount member
fwrite(&dwcount, sizeof(DWORD), 1, outfile);And this: DWORD dwcount = 0x01; //lpBmpPkg->dwCount;
// write the dwCount member
fwrite(&dwcount, sizeof(DWORD), 1, outfile);Strange, no?
__________________
Neeley.org |
||
|
|
|
|
|
#4 |
|
Programming Guru
![]() Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,223
Rep Power: 5
![]() |
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;
ZeroMemory(&bmppkg, sizeof(BMPPKGFILE));
// other things
bmppkg.dwCount = some_value;
for (DWORD i = 0; i < bmppkg.dwCount; ++i)
{
bmppkg.pEntries[i].dwEntrySize = something();
// more manipulation of bmppkg.pEntries[i]
} |
|
|
|
|
|
#5 |
|
Programmer
Join Date: Feb 2006
Location: Ohio
Posts: 93
Rep Power: 3
![]() |
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.
__________________
Neeley.org |
|
|
|
|
|
#6 |
|
Programmer
Join Date: Feb 2006
Location: Ohio
Posts: 93
Rep Power: 3
![]() |
Re: Read Access Violation
This caught my attention, btw... I wonder, is it possible that an earlier file read/write problem (somewhere in some other function, which does not report an error) could cause this particular fwrite failure?
__________________
Neeley.org |
|
|
|
|
|
#7 | |
|
Programming Guru
![]() Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,223
Rep Power: 5
![]() |
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. |
|
|
|
|
|
|
#8 |
|
Programmer
Join Date: Nov 2007
Posts: 33
Rep Power: 0
![]() |
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.
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut. |
|
|
|
|
|
#9 |
|
Programmer
Join Date: Feb 2006
Location: Ohio
Posts: 93
Rep Power: 3
![]() |
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.
__________________
Neeley.org |
|
|
|
|
|
#10 | |
|
Programming Guru
![]() Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,223
Rep Power: 5
![]() |
Re: Read Access Violation
Quote:
Laying out a program out in memory so it is possible to detect invalid memory accesses is expensive: results in a program that uses more memory, runs slower, etc, etc. Compiler/linker writers tend to be pressured by developers to produce "efficient" code so they normally do things by assuming code does not do memory overruns. Since the difference, performance wise, can be orders of magnitude, there is a lot of pressure on compiler writers to err on the side of performance at the cost of failing to detect all potential errors. This means that the layout of variables (or structures or dynamically allocated memory) is not designed to detect overruns. Two unrelated variables A and B may be placed placed adjacent in memory because that happens to be the "optimal" way of laying things out. Code which does an overrun while working with variable A can therefore overwrite variable B, but this will not be detected. If some other code comes along and accesses variable B, it will do something unintended and (probably) write wrong data somewhere else. These things tend to bubble along, until some confused code tromps an area of critical memory -- at which point an invalid access is detected and an error reported (eg exception is thrown). Products like Electric Fence work by laying out memory and other things so invalid memory accesses are more likely to be detected. In practice, they increase the odds of detecting invalid operations, but do not guarantee they will be detected. |
|
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| 1 line if code blocks; easier to read | G.I.Josh | Perl | 5 | Nov 6th, 2007 11:30 PM |
| read access violation | backstabber | C++ | 14 | Oct 13th, 2006 3:54 PM |
| Access to private files. | Jhaqen | Java | 2 | Nov 2nd, 2005 2:35 PM |
| How to connect with VB to an Access database on another computer | iown714 | Visual Basic | 5 | Aug 4th, 2005 10:23 AM |
| Access Violation Error | cornish_boy84 | Delphi | 1 | Mar 1st, 2005 4:12 PM |