C++ and Valgrind: Can't understand "Invalid read" error
Hi everybody!
I have just started using Valgrind,which really is great. Most of the reported errors look kinda weird,though... I can't really understand what's going on here, for example: Quote:
The address reported (0x47a5ee8) is 296 bytes after the "this" pointer (0x47a5dc0),as Valgrind correctly tells me,but i honestly don't understand that. And,of course,i need to read that variable,not only for the cout (indeed,the error is reported at every reading attempt). Besides, the application doesn't crash,but still i would like to understand if i really have to worry about this "error". Can you please help me? |
What is sizeof(MyCls)?
Is it possible the object size exceeds the memory allocation that contains the object? Can you disassemble a few asm instructions around 0x80B0987 (or disassemble MyCls::MyPrintf up through 0x80B0987 and post a few instructions around 0x80B0987). If Valgrind is just wrong, that disassembly might confirm that it is wrong and also give some clue what is confusing it. |
Thanks for your reply!
First of all,the size is: sizeof(MyCls)=304 The code for MyPrintf is: Quote:
I disassembled my program using: Quote:
Quote:
|
Quote:
Remember you quoted: Quote:
Hopefully, the part you didn't quote that appears right after the above in the Valgrind output tells you more about the call stack at the point the object was allocated. You should find that allocation in your code. What kind of object does it think it's allocating? Then how does it come to believe that is a pointer to MyCls. Another possibility for a bug with these symptoms: Maybe you had a pointer to an actual object of type MyCls. Then you deleted that object. Then you allocated an unrelated 296 byte object that happened to take the same memory location. Then the bug was in continuing to use the pointer to the MyCls object that had been deleted. |
You're right,the part i didn't quote leads to the declaration of a MyCls object.
Quote:
I checked about your last guess (when you say "Maybe you had a pointer to an actual object of type MyCls. Then you deleted that object."): that's not the case.I don't delete the object elsewhere in the code. Looking more carefully at the Valgrind report, i did notice that the same kind of problem (Invalid read of size 4) occurs also when the MyCls constructor is called (the line above). I also noticed that an Invalid write of the same size is reported as well. These errors occurs only when the m_FilePtr member variable is accessed , so the problem must be in that variable. Now...sorry for the stupid question: how is it possible that i'm allocating 296 bytes but the sizeof operator reports 304? What should i check to understand what's going on? Thanks for the help: i'm trying to figure out what's going on in a program written by somebody else,and i still need to learn some more :-) |
Quote:
Quote:
I don't know why that is happening. Some possibilities are: Stale .o files: You changed some source code but only recompiled some of the .o files that depend on that source code. Inconsistent definitions or compile options: You compiled multiple .cpp files that include the same definition of MyCls, but had some other definitions or compile options inconsistent between them causing MyCls to be different sizes. Multiple definitions of MyCls. |
Ok,i think i found the problem! And,obviously,thanks to you!
Basically,in the MyCls header file,there are 2 member variables that are declared ONLY if the macro ILOG is defined (i guess the original author decided to do this in order to provide a toggle the logging functionality). Quote:
I added the line of code: Quote:
Instead,as i already wrote,the cout i had placed in the MyCls::MyPrintf function reported a 304 size on every logging. Inserting #define ILOG at the beginning of the MyCls header file has removed the error report. I still have 2 doubts: 1)I wonder how this didn't lead to crashes...basically i think i was writing/reading from memory zones in which i couldn't have done it 2)Since the program is compiled using a custom makefile in which i could define the ILOG macro simply using the -D flag of gcc,is it better to use this option or stick to the #define at the top of MyCls header file? I do thank you for your help... I really don't think i could have figure it out by myself :-) |
Quote:
Quote:
Accessing beyond the end of a chunk can't directly crash unless that happens to access beyond the end of the contiguous group of 4096 byte pages. That is very rare. You were accessing just 8 bytes beyond the end of the chunk. Assuming the constructor was not inline, you were writing to those 8 bytes in the constructor. In most cases, those 8 bytes would be data used by malloc to keep track of the size and status of the following chunk of memory. For simple memory use patterns, that following chunk would probably have been free at the time you overwrote its control info. So the crash, if any, should occur during some subsequent attempt to allocate memory when malloc gets confused by the wrong info in those bytes describing the size and status of that free chunk. I don't know why that subsequent crash didn't occur. But in my experience, serious bugs with no symptoms are quite common. Later someone changes some unrelated part of the program and a symptom pops up. Quote:
|
Oh i wanted to let you know how much you helped me :)
And i'm really glad if somebody else will find the post useful! The constructor isn't inline:why would it be different? (sorry,as you probably noticed i still have to learn a lot... ). The crashes i got are also probably due to various bugs: so far i fixed 3 errors related to invalid reads/writes.... Gosh i was really mistreating memory! |
Quote:
So if the constructor is inline (defined in the hpp file) the constructor will use the incorrect size and layout, so it will not overwrite memory beyond the allocated size, so it will not cause a subsequent malloc to crash. But it will construct the object incorrectly, so subsequent use of any pointers in the incorrectly constructed portion of the object ought to crash. If the constructor is non inline (declared in the hpp but defined in the cpp), then it will construct the correct size and layout object using the incorrectly allocated space, so subsequent use of the current object should be OK, but memory beyond the object has been corrupted and should cause a later malloc to crash. |
Well,what to say.... Thank you again!
|
I just wanna say that valgrind gives me errors when comparing a NULL pointer etc:
struct areas *top == NULL; while ( top == NULL) if ( top== NULL) not sure why valgrind says theres an error when comparing but the program doesn't crash it works very good and here is a copy: http://o0oo0.net16.net/shared/ |
Quote:
I doubt valgrind has a flaw as bad as the one you describe, so I think you misunderstood the results you saw. |
I didn't say it was does valgrind give errors when you run that program?
|
Quote:
Notice the thread that is now above your post. You can see it isn't very hard to give enough info in a few posts to allow an expert to give useful guidance without requiring the expert to do the work himself. BTW, was all that above your post when I first answered you? (In other words, did you tack your post onto the bottom of a similar, but not really related, old thread?) I really thought I made my first reply to you (Oct-03-12) in a new thread with just your original question in it. Did some moderator merge these threads for some reason? |
All times are GMT -5. The time now is 05:45 PM. |