LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-25-2010, 11:21 AM   #1
Accinson
LQ Newbie
 
Registered: Feb 2009
Posts: 22

Rep: Reputation: 6
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:
==00:00:02:52.033 7754== Invalid read of size 4
==00:00:02:52.033 7754== at 0x80B0987: MyCls::MyPrintf(long, char*, ...) (MyCls.cpp:270)

...

==00:00:02:52.033 7754== Address 0x47a5ee8 is 0 bytes after a block of size 296 alloc'd

...

==00:00:02:52.033 7754== by 0x809A6C1: ClsMain::taskRun(int, char**) (ClsMain.cpp:177)
==00:00:02:52.033 7754== by 0x816CFE8: main (main-C.cpp:2060)

==7754== ---- Attach to debugger ? --- [Return/N/n/Y/y/C/c] ---- Y
==00:00:02:57.410 7754== starting debugger with cmd: /usr/bin/gdb -nw /proc/7765/fd/1014 7765
GNU gdb Red Hat Linux (6.5-25.el5rh)
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

Attaching to program: /proc/7765/fd/1014, process 7765
MyCls::MyPrintf (this=0x47a5dc0, iPrm=3,
sMsg=0x6974320 "blablabla\n"...) at MyCls.cpp:270

270 cout<<endl<<"m_FilePtr="<<hex<<m_FilePtr<<dec<<endl;
Basically,Valgrind reported the "Invalid Read" error at line 270 of file MyCls.cpp, which is simply a cout of the m_FilePtr variable, which is a member variable of the MyCls class. It's a FILE* variable i use to write repeatedly on a text file.
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?
 
Click here to see the post LQ members have rated as the most helpful post in this thread.
Old 08-25-2010, 11:55 AM   #2
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
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.
 
Old 08-26-2010, 09:01 AM   #3
Accinson
LQ Newbie
 
Registered: Feb 2009
Posts: 22

Original Poster
Rep: Reputation: 6
Thanks for your reply!

First of all,the size is:
sizeof(MyCls)=304

The code for MyPrintf is:
Quote:
245 void MyCls::MyPrintf (long iPrm, char *sMsg, ...)
246 {
247 char sMsgLogString[g_iMaxMsgLogString];
248 va_list arg;
249 int iBytesWritten = 0;
250
251 if (NULL == m_FilePtr)
252 {
253 return;
254 }
255
256 va_start(arg, sMsg);
257 iBytesWritten = vsprintf(sMsgLogString, sMsg, arg);
258 va_end(arg);
259
260 if (iBytesWritten <= 0)
261 {
262 return;
263 }
264
265 sMsgLogString[iBytesWritten] = '\n';
266 sMsgLogString[iBytesWritten + 1] = '\0';
267
268
269 //test
270 cout<<endl<<endl<<endl<<"m_FilePtr="<<hex<<m_FilePtr<<dec<<endl;
271 cout<<"---------------"<<endl<<endl;
272 //end test
273
274 fputs(sMsgLogString, m_FilePtr);
275 }
Valgrind actually reports the same kind of error i posted not only for line 270,but also 251 and 274: the common operation done in these lines is the reading of m_FilePtr.

I disassembled my program using:
Quote:
objdump -Dslx testProg
I got the following:
Quote:
/home/Test/MyCls.cpp:251
80b0943: 83 bf 28 01 00 00 00 cmpl $0x0,0x128(%edi)
80b094a: 0f 84 cd 00 00 00 je 80b0a1d <_ZN8MyCls9MyPrintfElPcz+0xef>

/home/Test/MyCls.cpp:256
80b0950: 8d 45 14 lea 0x14(%ebp),%eax
80b0953: 89 45 f0 mov %eax,0xfffffff0(%ebp)

/home/Test/MyCls.cpp:257
80b0956: 89 44 24 08 mov %eax,0x8(%esp)
80b095a: 8b 45 10 mov 0x10(%ebp),%eax
80b095d: 89 44 24 04 mov %eax,0x4(%esp)
80b0961: 8d 85 f0 df ff ff lea 0xffffdff0(%ebp),%eax
80b0967: 89 04 24 mov %eax,(%esp)
80b096a: e8 d5 fe f9 ff call 8050844 <vsprintf@plt>

/home/Test/MyCls.cpp:260
80b096f: 85 c0 test %eax,%eax
80b0971: 0f 8e a6 00 00 00 jle 80b0a1d <_ZN8MyCls9MyPrintfElPcz+0xef>

/home/Test/MyCls.cpp:265
80b0977: c6 84 05 f0 df ff ff movb $0xa,0xffffdff0(%ebp,%eax,1)
80b097e: 0a

/home/Test/MyCls.cpp:266
80b097f: c6 84 05 f1 df ff ff movb $0x0,0xffffdff1(%ebp,%eax,1)
80b0986: 00

/home/Test/MyCls.cpp:270
80b0987: 8b b7 28 01 00 00 mov 0x128(%edi),%esi
_ZNSolsEPFRSoS_E():

/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/ostream.tcc:72
80b098d: c7 04 24 18 2e 2a 08 movl $0x82a2e18,(%esp)
80b0994: e8 4b f7 f9 ff call 80500e4

<_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@plt>
_ZN8MyCls9MyPrintfElPcz():
/home/Test/MyCls.cpp:270
80b0999: c7 44 24 04 3a e0 19 movl $0x819e03a,0x4(%esp)
80b09a0: 08
80b09a1: 89 04 24 mov %eax,(%esp)
80b09a4: e8 db ff f9 ff call 8050984

<_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
80b09a9: 89 c3 mov %eax,%ebx
_ZNSolsEPFRSt8ios_baseS0_E():
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/ostream.tcc:95
80b09ab: 8b 00 mov (%eax),%eax
80b09ad: 8b 50 f4 mov 0xfffffff4(%eax),%edx
80b09b0: 8d 04 13 lea (%ebx,%edx,1),%eax
80b09b3: 89 04 24 mov %eax,(%esp)
80b09b6: e8 23 0b 00 00 call 80b14de

<_ZSt3hexRSt8ios_base>
_ZN8MyCls9MyPrintfElPcz():
/home/Test/MyCls.cpp:270
80b09bb: 89 74 24 04 mov %esi,0x4(%esp)
80b09bf: 89 1c 24 mov %ebx,(%esp)
80b09c2: e8 8d fb f9 ff call 8050554 <_ZNSolsEPKv@plt>
80b09c7: 89 c3 mov %eax,%ebx

_ZNSolsEPFRSt8ios_baseS0_E():
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/ostream.tcc:95
80b09c9: 8b 00 mov (%eax),%eax
80b09cb: 8b 50 f4 mov 0xfffffff4(%eax),%edx
80b09ce: 8d 04 13 lea (%ebx,%edx,1),%eax
80b09d1: 89 04 24 mov %eax,(%esp)
80b09d4: e8 d5 08 00 00 call 80b12ae

<_ZSt3decRSt8ios_base>
_ZNSolsEPFRSoS_E():
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/ostream.tcc:72
80b09d9: 89 1c 24 mov %ebx,(%esp)
80b09dc: e8 03 f7 f9 ff call 80500e4

<_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@plt>
_ZN8MyCls9MyPrintfElPcz():
/home/Test/MyCls.cpp:271
80b09e1: c7 44 24 04 4c e0 19 movl $0x819e04c,0x4(%esp)
80b09e8: 08
80b09e9: c7 04 24 18 2e 2a 08 movl $0x82a2e18,(%esp)
80b09f0: e8 8f ff f9 ff call 8050984

<_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
_ZNSolsEPFRSoS_E():
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/ostream.tcc:72
80b09f5: 89 04 24 mov %eax,(%esp)
80b09f8: e8 e7 f6 f9 ff call 80500e4

<_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@plt>
/home/Test/MyCls.cpp:274
80b09fd: 89 04 24 mov %eax,(%esp)
80b0a00: e8 df f6 f9 ff call 80500e4

<_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@plt>
_ZN8MyCls9MyPrintfElPcz():
80b0a05: 8b 87 28 01 00 00 mov 0x128(%edi),%eax
80b0a0b: 89 44 24 04 mov %eax,0x4(%esp)
80b0a0f: 8d 85 f0 df ff ff lea 0xffffdff0(%ebp),%eax
80b0a15: 89 04 24 mov %eax,(%esp)
80b0a18: e8 b7 fd f9 ff call 80507d4 <fputs@plt>

 
Old 08-26-2010, 09:23 AM   #4
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by Accinson View Post
First of all,the size is:
sizeof(MyCls)=304
I'm glad I asked that. So forget about what happens where that object is accessed. The problem is where the pointer to that object is created, probably in a cast from the wrong type.

Remember you quoted:
Quote:
Address 0x47a5ee8 is 0 bytes after a block of size 296 alloc'd
So you allocated a 296 byte object and then used it as a 304 byte object.

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.
 
1 members found this post helpful.
Old 08-26-2010, 11:24 AM   #5
Accinson
LQ Newbie
 
Registered: Feb 2009
Posts: 22

Original Poster
Rep: Reputation: 6
You're right,the part i didn't quote leads to the declaration of a MyCls object.

Quote:
obj_tskTestQ = new MyCls("/INMsgQ");
where the only constructor parameter is the name of a posix message queue i'm using to store message received by rpc protocol.The m_FilePtr is a pointer to the file in which i'm logging every message.

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 :-)
 
Old 08-26-2010, 11:38 AM   #6
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by Accinson View Post
These errors occurs only when the m_FilePtr member variable is accessed , so the problem must be in that variable.
No. That is just a side effect of the confusion about the size of the object.

Quote:
Now...sorry for the stupid question: how is it possible that i'm allocating 296 bytes but the sizeof operator reports 304?
That is not a stupid question. That seems to be the heart of the problem.

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.
 
3 members found this post helpful.
Old 08-27-2010, 03:35 AM   #7
Accinson
LQ Newbie
 
Registered: Feb 2009
Posts: 22

Original Poster
Rep: Reputation: 6
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:
#ifdef ILOG
FILE* m_FilePtr;
int m_iFileDescriptor;
#endif
The macro ILOG,though is #defined only in the MyCls cpp file.

I added the line of code:
Quote:
obj_tskTestQ = new MyCls("/INMsgQ");
cout<<"Class size:"<<sizeof(MyCls)<<" - Object size:"<<sizeof(*obj_tskTestQ)<<endl;//Added this
That cout reported me a size of 296 bytes both for the class and object.
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 :-)
 
1 members found this post helpful.
Old 08-27-2010, 07:34 AM   #8
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by Accinson View Post
i think i found the problem!
I'm glad you posted that. Too many people ask a question or even a series of followup questions and then stop posting after some good suggestion. It's frustrating to wonder whether they gave up or whether they reached the solution but didn't bother to share. Also the solution may help someone who finds the thread later searching a similar problem.

Quote:
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
Memory is allocated from the Linux kernel to your process's malloc system as large contiguous groups of 4096 byte pages. Malloc then sub allocates that into the chunks your program requests.

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:
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?
That would depend on how ILOG is used elsewhere in the project and on the conditions under which you might change your mind about whether you want those optional members in MyCls. That may be an impossible decision to make well without understanding the intent of the original programmer.
 
2 members found this post helpful.
Old 08-27-2010, 03:02 PM   #9
Accinson
LQ Newbie
 
Registered: Feb 2009
Posts: 22

Original Poster
Rep: Reputation: 6
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!
 
Old 08-27-2010, 03:18 PM   #10
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by Accinson View Post
The constructor isn't inline:why would it be different? (sorry,as you probably noticed i still have to learn a lot... ).
The constructor was called from code that had an incorrect size and layout for the object.

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.

Last edited by johnsfine; 08-27-2010 at 03:24 PM.
 
2 members found this post helpful.
Old 08-27-2010, 03:26 PM   #11
Accinson
LQ Newbie
 
Registered: Feb 2009
Posts: 22

Original Poster
Rep: Reputation: 6
Well,what to say.... Thank you again!
 
Old 10-02-2012, 10:57 PM   #12
errigour
Member
 
Registered: May 2009
Posts: 366

Rep: Reputation: 6
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/
 
Old 10-03-2012, 07:43 AM   #13
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by errigour View Post
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/
There is no such line in the source code you linked to.

I doubt valgrind has a flaw as bad as the one you describe, so I think you misunderstood the results you saw.
 
Old 10-03-2012, 05:24 PM   #14
errigour
Member
 
Registered: May 2009
Posts: 366

Rep: Reputation: 6
I didn't say it was does valgrind give errors when you run that program?
 
Old 10-04-2012, 07:32 AM   #15
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by errigour View Post
I didn't say it was does valgrind give errors when you run that program?
I don't plan to try your program in Valgrind. If you had provided sufficient info in your post for me to give helpful advice, I would have attempted that. Maybe someone else will try your program in Valgrind.

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?
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Getting "Short read in buffer_copy" error with "dpkg" stalefries Linux - Software 6 03-24-2010 03:19 PM
ns:"error when calling class OldSim"&tclsh:"invalid command+child process exits abn." shojaru Linux - Newbie 0 03-05-2009 04:23 AM
error: Error for wireless request "Set Mode" (8B06) : invalid argument "roaming" penguin chick Linux - Wireless Networking 5 08-22-2008 01:16 PM
"capset: Operation not permitted" error when I run valgrind. rsravi74 Linux - Newbie 1 09-02-2007 05:30 PM
valgrind crashes at start up with "Killed" error message lasindi Slackware 0 04-22-2006 08:54 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:53 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration