Solved

STL map and pair causing memory access error

Posted on 2009-07-09
36
728 Views
Last Modified: 2013-12-27
Dear Sir/madam,

I am working on Solaris 8.
dbx is showing memory access error in the following line:

emplate<class keyType_t, class dataType_t>
int WrapperC<keyType_t, dataType_t>::insert(keyType_t keyVal,
dataType_t& info_t )
{
pair<map<keyType_t,dataType_t>::iterator,bool> retItor;
retItor = subsInfoMap_obj.insert( pair<keyType_t, dataType_t>(keyVal, info_t
) );
........
};

WrapperC class is derived from an abstract class which is as follows:

</code>
template<class keyType_t, class dataType_t>
class ContAbsC
{
public:
ContAbsC( keyType_t, dataType_t );
virtual int insertElementInto( keyType_t, dataType_t& ) = 0 ;
protected:
keyType_t keyValue;
dataType_t info;
};

template<class keyType_t, class dataType_t>
class WrapperC : public ContAbsC<keyType_t, dataType_t>
{

protected:
map<keyType_t, dataType_t> Map_obj;
typedef map<keyType_t, dataType_t> InfoMap;
typename typedef map<keyType_t, dataType_t>::iterator InfoMap_itor;
typedef typename pair<typename map<keyType_t,dataType_t>::iterator,bool> Map_pairItor;
public:
WrapperC( keyType_t, dataType_t);
virtual int insert( keyType_t, dataType_t& ) ;

//Copy constructor
WrapperC( const WrapperC& Wrapper_o );
//Assignment Operator Overlaoding
WrapperC& operator= ( const WrapperC& mapWrapper_o );
};


dbx is showing similar access errors in lot of other places also. Please guide me to solve this problem.

Thanks in advance
template<class keyType_t, class dataType_t>

int WrapperC<keyType_t, dataType_t>::insert(keyType_t keyVal,

dataType_t& info_t )

{

pair<map<keyType_t,dataType_t>::iterator,bool> retItor;

retItor = subsInfoMap_obj.insert( pair<keyType_t, dataType_t>(keyVal, info_t

) );

........

};
 
 

template<class keyType_t, class dataType_t>

class ContAbsC

{

public:

ContAbsC( keyType_t, dataType_t );

virtual int insertElementInto( keyType_t, dataType_t& ) = 0 ;

protected:

keyType_t keyValue;

dataType_t info;

};
 

template<class keyType_t, class dataType_t>

class WrapperC : public ContAbsC<keyType_t, dataType_t>

{
 

protected:

map<keyType_t, dataType_t> Map_obj;

typedef map<keyType_t, dataType_t> InfoMap;

typename typedef map<keyType_t, dataType_t>::iterator InfoMap_itor;

typedef typename pair<typename map<keyType_t,dataType_t>::iterator,bool> Map_pairItor;

public:

WrapperC();

WrapperC(dataType_t);

WrapperC( keyType_t, dataType_t);

virtual int insert( keyType_t, dataType_t& ) ;
 

//Copy constructor

WrapperC( const WrapperC& Wrapper_o );

//Assignment Operator Overlaoding

WrapperC& operator= ( const WrapperC& mapWrapper_o );

};

Open in new window

0
Comment
Question by:lakshmikarle
  • 13
  • 12
  • 8
  • +1
36 Comments
 
LVL 53

Expert Comment

by:Infinity08
ID: 24811526
What kind of access errors ?
0
 
LVL 1

Author Comment

by:lakshmikarle
ID: 24811719
This is exactly what dbx is saying
'Read from uninitialized (rui):Attempting to read 4 bytes at address 0xffbee3e0    which is 192 bytes above the current stack pointer'
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24811955
An rui indication means that the code is trying to access allocated memory that hasn't been initialized yet. You'd get it for this for example :

        int value;                        // <-- not initialized
        int copy = value;             // <-- reading an uninitialized value

So, make sure you initialize all variables before you use them. In fact, you should probably initialize ALL variables as soon as you define them.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24812035
>>>> dbx is showing memory access error in the following line:
It would be more interesting to have the code where you were calling the insert.

Especially what were the key type and value types of the map used?

>>>> Attempting to read 4 bytes at address 0xffbee3e0
>>>>   which is 192 bytes above the current stack pointer'

That could mean that you accessed memory already freed, i. e. using a pointer from a local class object after the scope it was defined:

AnyClass* f()
{
     AnyClass any;
     return &any;
}

int main()
{
     AnyClass* p = f();    // p now points to any which already was freed after call
     std::map<std::string, Any> anymap;
     anymap["abc"] = *p;   // kaboom
     
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24812083
>> That could mean that you accessed memory already freed

No, because then he would have had an rua (read from unallocated memory), rather than an rui (read from uninitialized memory).
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24812456
>>>> which is 192 bytes above the current stack pointer'
uninitialized memory shouldn't be beyond stack pointer
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24813109
>> uninitialized memory shouldn't be beyond stack pointer

It doesn't say 'beyond'. It says 'above'. And the stack is likely growing downwards.
Even if it is reading beyond the stack pointer, that isn't necessarily a problem either, since due to optimization, it could be that the stack pointer wasn't updated.


lakshmikarle, if you have made sure to initialize all data before using it, and you still get these rui's, then they might be false positives. dbx is known to generate false positives for struct padding for example.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24813253
>>>>It doesn't say 'beyond'. It says 'above'.

yes, I stand corrected ;-)
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24813275
@lakshmikarle,

please post the code which uses the map. We only can make guesses and speculations without it.
0
 
LVL 1

Author Comment

by:lakshmikarle
ID: 24820699
Thanks for your time.
I have attached the code here. Following line:

" virtual int insert( keyType1_t keyVal, dataType1_t& info_t)    {            pair<map<keyType1_t,dataType1_t>::iterator,bool> retItor;"

is causing dbx error.

If dbx is showing these access errors because of padding, can you elaborate on what is happening exactly?

#include<iostream>

#include<map>

using namespace std;
 

struct MsgS

{

       unsigned long key;

       int element;

};
 

template<class keyType_t, class dataType_t>

class AbsC

{

    public:

        AbsC();

        AbsC( keyType_t, dataType_t );

        virtual int insert( keyType_t, dataType_t& ) = 0 ;

        virtual int remove( keyType_t, dataType_t* ) = 0 ;

        virtual int search( keyType_t, dataType_t* ) = 0 ;

        ~AbsC();

        

    protected:

        keyType_t keyValue;

        dataType_t info;
 

};
 

template<class keyType1_t, class dataType1_t>

class WrapperC : public AbsC<keyType1_t, dataType1_t> 

{
 

    protected:

        map<keyType1_t, dataType1_t> InfoMap_obj;

        typedef map<keyType1_t, dataType1_t> InfoMap;

        typename typedef map<keyType1_t, dataType1_t>::iterator InfoMap_itor;

        typedef typename pair<typename map<keyType1_t,dataType1_t>::iterator,bool> InfoMap_pairItor;

    public:

        WrapperC( keyType1_t arg1, dataType1_t arg2) ;
 

        virtual int insert( keyType1_t keyVal, dataType1_t& info_t) 

	{

    		pair<map<keyType1_t,dataType1_t>::iterator,bool> retItor;

    		retItor = InfoMap_obj.insert( pair<keyType1_t, dataType1_t>(keyVal, info_t ) );

    

    		if ( retItor.second == false )

    		{

        		cout<<"\n Element alread exists";

        		return (-1);

    		}

    		return (1);

	};
 

        virtual int remove( keyType1_t keyVal, dataType1_t* info_tp) 

	{

    		InfoMap_itor retItor;

    		retItor =  InfoMap_obj.find(keyVal) ;

    		if(retItor == InfoMap_obj.end())

    		{

        		cout <<"\n key not found";

        		info_tp = NULL;

        		return (-1);

    		}

    		*info_tp = retItor->second;

    		InfoMap_obj.erase( InfoMap_obj.find(keyVal) );

    		return (1);

	};
 

        virtual int search( keyType1_t keyVal, dataType1_t* info_tp) 

	{

    		//dataType_t infoRet;

    		InfoMap_itor retItor;

    		retItor = InfoMap_obj.find( keyVal );

    		if(retItor == InfoMap_obj.end() )

    		{

        		cout<<"\n key not found";

        		cout << endl << "search key: \"" << keyVal << "\"" << endl;

        		//displayDataFrom();

        		info_tp = NULL;

        		return ( -1 );

    		}

    		*info_tp = retItor->second;

    		return( 1 );

	};

        ~WrapperC(){};
 

        //Copy constructor 

        WrapperC( const WrapperC& mapWrapper_o )

	{

   		if( &mapWrapper_o != NULL ) 

   		{

       			this->subsInfoMap_obj = mapWrapper_o.InfoMap_obj ;

   		}

	};

        //Assignment Operator Overlaoding

        WrapperC& operator= ( const WrapperC& mapWrapper_o )

	{

   		if( ( this != &mapWrapper_o ) && ( &mapWrapper_o != NULL ) )

   		{

       			this->InfoMap_obj = mapWrapper_o.InfoMap_obj ;

       			this->noOfElem_ul = mapWrapper_o.noOfElem_ul ;

   		}

   		return ( *this ) ;

	};

};
 

template<class keyType_t, class dataType_t>

AbsC<keyType_t, dataType_t>::AbsC()

{

}
 

template<class keyType_t, class dataType_t>

AbsC<keyType_t, dataType_t>::AbsC( keyType_t argkeyValue, dataType_t info_t)

{

    info = info_t;

    keyValue = argkeyValue;

}
 

template<class keyType_t, class dataType_t>

AbsC<keyType_t, dataType_t>::~AbsC()

{

}
 

template<class keyType1_t, class dataType1_t>

WrapperC<keyType1_t, dataType1_t>::WrapperC( keyType1_t key_t, dataType1_t info_t):AbsC( key_t, info_t)

{

}
 

int main()

{

        struct MsgS msgS;

        struct MsgS* msgR;

        msgR = new struct MsgS;

        msgS.key = 123456;

        msgS.element = 1;

	WrapperC<unsigned long, struct MsgS> objS(msgS.key, msgS);

	int b = objS.insert( msgS.key, msgS);

	//int b = objS.insert( msgS.key, msgS.key);

        // adding 2 element

        msgS.key = 123454;

        msgS.element = 2;

	b = objS.insert( msgS.key, msgS);

        //remove elem

        b = objS.remove(12, msgR);

        if ( b == 1 )

        	cout<<"\n ret value for remove elem "<<msgR->key << "\t" << msgR->element<<endl;

        b = objS.remove(123456, msgR);

        if ( b == 1 )

        	cout<<"\n ret value for remove elem "<<msgR->key << "\t" << msgR->element<<endl;

        b = objS.search(78912, msgR);

        if ( b ==1 )

        	cout<<"\n ret value for search elem "<<msgR->key << "\t" << msgR->element<<"\n";

        b = objS.search(123454, msgR);

        if ( b == 1 )

        	cout<<"\n ret value for search elem "<<msgR->key << "\t" << msgR->element<<endl;

	return 1;

}

Open in new window

0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24820831
A look over the code does not show any use of non-initialized values (I might be missing one though).

>> If dbx is showing these access errors because of padding, can you elaborate on what is happening exactly?

I'm not saying that that is what's happening, but that that is one of the scenario's where dbx might give a false rui.
The reason is that if you copy a struct into another, it copies it with the data and padding included. But generally, that padding hasn't been initialized, so you're basically copying uninitialized data. That would be a false positive, because that padding is never actually used, so the fact whether it's initialized or not doesn't really matter.

For example, you initialize a struct like this :

>>         struct MsgS msgS;
>>         msgS.key = 123456;
>>         msgS.element = 1;

If the struct contains any padding (ie. if sizeof(msgS) > sizeof(unsigned long) + sizeof(int)), and you try to copy it, like in a function call while passing it by value :

>>         WrapperC<unsigned long, struct MsgS> objS(msgS.key, msgS);

or more explicitly :

>>                 *info_tp = retItor->second;

you could get a false rui because of the padding.

Note that, as I said, padding is only one of the reasons that dbx might throw a false positive rui.


Now, you could easily check this, by initializing the whole struct including padding, and seeing if the same rui occurs. For example, using memset :

        struct MsgS msgS;
        memset(&msgS, 0, sizeof(MsgS));


If that doesn't help, could you please post the complete dbx report, including the stack traces and everything ?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24820960
>>>> Following line:
>>>> " virtual int insert( keyType1_t keyVal, dataType1_t& info_t)
>>>>    {
>>>>           pair<map<keyType1_t,dataType1_t>::iterator,bool> retItor;"
>>>> is causing dbx error.

That is not causing the error but that *is* the error line.

We would need the statement where the insert function was called with concrete template types for keyType1_t or dataType1_t.

The uninitialized memory probably is in the info_t argument where the insert will make a copy of.

If you have many 'insert' calls in your code, post the functions which most probably were called before the crash.
0
 
LVL 1

Author Comment

by:lakshmikarle
ID: 24821070
itmeansnobodyelse,
In my previous comment, I have attached complete executable working code which contains concrete template types

I tried memset  memset(&msgS, 0, sizeof(MsgS));, but the error persists. I have attached the dbx report

-Thanks in advance
0
 
LVL 1

Author Comment

by:lakshmikarle
ID: 24821077
dbx report:

Attempting to read 4 bytes at address 0xffbee8c8
    which is 192 bytes above the current stack pointer
=>[1] __rwstd::__rb_tree<unsigned long,std::pair<const unsigned long,MsgS>,__rwstd::__select1st<std:
:pair<const unsigned long,MsgS>,unsigned long>,std::less<unsigned long>,std::allocator<std::pair<con
st unsigned long,MsgS> > >::iterator::iterator(0xffbee93c, 0xffbee8c8, 0x2, 0xfb8, 0xfe960c00, 0xff8
), at 0x305f4
  [2] std::pair<__rwstd::__rb_tree<unsigned long,std::pair<const unsigned long,MsgS>,__rwstd::__sele
ct1st<std::pair<const unsigned long,MsgS>,unsigned long>,std::less<unsigned long>,std::allocator<std
::pair<const unsigned long,MsgS> > >::iterator,bool>::pair(this = 0xffbee93c), line 106 in "utility"
  [3] WrapperC<unsigned long,MsgS>::insert(this = 0xffbeea0c, keyVal = 123456U, info_t = STRUCT), li
ne 42 in "sample.cc"
  [4] main(), line 138 in "sample.cc"

<rtc> Read from uninitialized (rui):
Attempting to read 4 bytes at address 0xffbee8c8
    which is 192 bytes above the current stack pointer
=>[1] __rwstd::__rb_tree<unsigned long,std::pair<const unsigned long,MsgS>,__rwstd::__select1st<std:
:pair<const unsigned long,MsgS>,unsigned long>,std::less<unsigned long>,std::allocator<std::pair<con
st unsigned long,MsgS> > >::iterator::iterator(0xffbee93c, 0xffbee8c8, 0x2, 0xfb8, 0xfe960c00, 0xff8
), at 0x305f4
  [2] std::pair<__rwstd::__rb_tree<unsigned long,std::pair<const unsigned long,MsgS>,__rwstd::__sele
ct1st<std::pair<const unsigned long,MsgS>,unsigned long>,std::less<unsigned long>,std::allocator<std
::pair<const unsigned long,MsgS> > >::iterator,bool>::pair(this = 0xffbee93c), line 106 in "utility"
  [3] WrapperC<unsigned long,MsgS>::insert(this = 0xffbeea0c, keyVal = 123454U, info_t = STRUCT), li
ne 42 in "sample.cc"
  [4] main(), line 143 in "sample.cc"

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24821137
>>>> I have attached complete executable working code which contains concrete template typ

Sorry, I didn't scroll down.

Do you know which of the both insert statements causes the error?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24821189
>>>> I tried memset  memset(&msgS, 0, sizeof(MsgS));, but the error persists.

Use

   struct MsgS msgS = { 0 };

what is much easier. I don't think it is a padding issue. A structure with two integer types never should be a matter of padding. Moreover, why should a consecutive function should care for uninitialized paddings ...

You see in the dump that the address where the rui was reported was past as second argument to the constructor of the iterator. Maybe Infinity knows what the second argument actually is.

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24821287
I ran your code at my system (VC8, WinXP) and it runs without problems.

So, it indeed might be a wrong indication as Infinity assumed.

Did you try


    struct MsgS msgS = { 0 };


or

    struct MsgS msgS = { 123456, 1 };


?

0
 
LVL 1

Author Comment

by:lakshmikarle
ID: 24821437
I used  struct MsgS msgS = { 0 };

It is not giving any problem in this program though dbx displays access error for it. But it might cause problem in  big software.

How can I confirm that this is a wrong indication and not a bug? There should be some reason .
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 53

Expert Comment

by:Infinity08
ID: 24821648
>> I have attached the code here.

I ran your code through dbx on a Solaris 9 machine (with Sun Studio 11), and didn't get any rui. So, I think it's safe to assume it's a false positive, or alternatively due to a compiler bug ...
Note that Solaris 8 is quite old ;) And I don't know what compiler (and version) you are using, or what version of dbx you are using, but I assume they're equally old.

From the stack traces you posted, it seems like the rui occurs when copying the pair returned by the insert. Although that shouldn't happen (unless it's a compiler bug or STL library bug or dbx bug), you might try a few things to try to trick it into not generating the rui. Like :

1) put it on one line :

        pair<map<keyType1_t,dataType1_t>::iterator,bool> retItor = InfoMap_obj.insert( pair<keyType1_t, dataType1_t>(keyVal, info_t ) );

2) use a different version of insert (just for testing purposes) :

        map<keyType1_t, dataType1_t>::iterator it = InfoMap_obj.insert(InfoMap_obj.begin(), pair<keyType1_t, dataType1_t>(keyVal, info_t));


In any case, if there is a problem, it's not in your code - it's either in the STL library or in the compiler. So, what compiler (and version) are you using ? What version of dbx are you using ?
Could you upgrade any of them ?




>>    struct MsgS msgS = { 0 };

This will not necessarily initialize the padding (some compilers do, but there's no such guarantee in the C++ standard), which was entirely the point of the memset ;)


>> I don't think it is a padding issue.

lakshmikarle already confirmed it wasn't, since using the memset didn't make a difference. If you'll read back over my previous reply, you'll also notice that the padding was just one of the many possibilities for a false positive rui.


>> A structure with two integer types never should be a matter of padding.

Never say never ... The C++ standard does not guarantee anything like that, so you cannot assume anything like it either.


>> Moreover, why should a consecutive function should care for uninitialized paddings ...

The function doesn't care about it. dbx is a debugger, which analyses the code at runtime, and only looks at what really happens in the CPU and in memory. It doesn't care about the original C++ code. If it notices that a piece of memory is read that hasn't been initialized (no matter for what reason), it will throw a rui.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24821664
>> lakshmikarle already confirmed it wasn't

For the specific struct in question - it might still be a padding issue for a different struct (like the iterator or the pair for example). But again - that's just conjecture.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24821714
Oh, and for the record : I still think the most likely reason for the rui is a false positive.
0
 
LVL 39

Assisted Solution

by:itsmeandnobodyelse
itsmeandnobodyelse earned 50 total points
ID: 24822048
>>>> If it notices that a piece of memory
Maybe not quite correct. In the above dump the address where the rui was reported wasn't any arbitrary address but the address of an argument passed to the constructor of an iterator class. Addresses of padding bytes rarely will be passed as arguments. That is what I told with 'why should a consecutive function should care for uninitialized paddings '

>>>> I don't think it is a padding issue.
>>>> If you'll read back over my previous rep
It was directed to lakshmikarle not to you.

>>>>  struct MsgS msgS = { 0 };  .... The C++ standard does not guarantee
Your advice implies it is better to using memset than  = { 0 };  

That is bad advice. Even if it was true that the C++ standard doesn't guarantee it (what I don't believe, btw), there is not the slightest reason for changing the behavior to somewhat where the members were zeroed and the paddings not.


>>>> Never say never ... The C++ standard ... you won't be able to assume ...

Why do you think you can advice me on what I can assume or not?


>>>> 2) use a different version of insert (just for) :

That is good advice (not only for  testing purposes).

What about

   
   virtual int insert( keyType1_t keyVal, dataType1_t& info_t) 

   {

      if ( InfoMap_obj.find(keyVal) != InfoMap_obj.end() )

    		{

            cout<<"\n Element already exists";

            return (-1);

    		}

      InfoMap_obj[keyVal] = info_t;

      return (1);

   };

Open in new window

0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24822396
>> Addresses of padding bytes rarely will be passed as arguments.

As I've said a few times already : padding is not the only possible reason for a false positive rui.
And the context of what you quoted ("If it notices that a piece of memory ") wasn't even about false positive rui's or padding - it was about dbx noticing a rui. You're mixing up contexts.


>> Your advice implies it is better to using memset than  = { 0 };  

No, it does not. The memset was simply to check whether it was a false positive rui due to padding. This is what I said literally :

        "Now, you could easily check this, by initializing the whole struct including padding, and seeing if the same rui occurs. For example, using memset"

Please don't twist my words.


>> Even if it was true that the C++ standard doesn't guarantee it (what I don't believe, btw)

Well, then read the C++ standard, and find out for yourself, if you don't believe me.
Find me the location in the C++ standard where it is guaranteed that struct padding is initialized when the struct is initialized using a brace-enclosed list, and I'll gladly admit that I was wrong. Until then, you're free to believe anything you want, but that doesn't make your beliefs correct, and you shouldn't mind me pointing out when they are in fact not correct.

Start with paragraph 8.5 ("Initializers"), and then 8.5.1 ("Aggregates").


>> Why do you think you can advice me on what I can assume or not?

Euhm ... if the C++ standard doesn't guarantee it, then you cannot assume it, since that would be dangerous. The only thing you can be sure of with a standards compliant compiler, is what is guaranteed by the standard. The rest is implementation dependent, and thus unreliable (especially since we don't even know what compiler lakshmikarle is using).
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24822539
I said
>>>> why should a consecutive function should care for uninitialized paddings ...
You said (as a response)
>>>>  If it notices that a piece of memory is read that hasn't been initialized (no matter for what reason), it will throw a rui

We have a concrete address where the uninitialized memory was located by dbx.

That address was the same as the address of the 2. argument in a call that was reported by dbx.

==> that address is definitively not an address to padding characters of a structure.

q.e.d.

>>>> wasn't even about false positive rui's or padding - it was about dbx noticing a rui.
You might read your comment again.

>>>> Your advice implies it is better to using memset than  = { 0 };  
>>>>>> No, it does not.

It was not an answer to my recommendation of using = { };  ????????


>>>> Find me the location in the C++ standard where it is guaranteed that struct padding is initialized
No, it is not me who had to prove. You made trhe objection, not me.

>>>> if the C++ standard doesn't guarantee it, then you cannot assume it, since that would be dangerous.
Oh dangerous? Any concrete dangers? No?









 
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24822665
>> ==> that address is definitively not an address to padding characters of a structure.
>>
>> q.e.d.

Why do you insist on the padding ? How many times do you want me to say that the padding is no longer an issue, and that it is not the only reason for a false positive rui ? Why keep going on about this ?


>> >>>> wasn't even about false positive rui's or padding - it was about dbx noticing a rui.
>> You might read your comment again.

Let me help you. This is what I said :

        "dbx is a debugger, which analyses the code at runtime, and only looks at what really happens in the CPU and in memory. It doesn't care about the original C++ code. If it notices that a piece of memory is read that hasn't been initialized (no matter for what reason), it will throw a rui."

This whole quote is about dbx, and how it finds rui's. Nothing in that whole quote mentions anything about false positive rui's or padding.


>> It was not an answer to my recommendation of using = { };  ????????

Please read this whole thread again, because I think you've lost track of the discussion :

* I suggested to use memset to check whether it was a false positive rui due to padding.
* You said that one should use a brace enclosed initializer list instead.
* I said that that would defeat the purpose, since the whole point was to initialize the padding (for test purposes), and a brace enclosed initializer list doesn't do that.
* You then said that the memset was bad advice.
* I said you were twisting my words, since I never advised to use memset other than for testing whether it was a false positive rui due to padding.
* You continue to make an issue out of this for some reason.


>> No, it is not me who had to prove. You made trhe objection, not me.

I did point you to the paragraphs in the C++ standard that explain this, didn't I ? You've already made clear that you don't believe what I say, so the only way for me to prove that I'm right is to have you read it in the standard for yourself. How else would you like me to prove it ?


>> Oh dangerous? Any concrete dangers? No?

Unfounded assumptions are always dangerous, precisely because they are unfounded.



Anyway, that's it for me, Alex. I'm getting back to trying to help lakshmikarle. If you want to continue these pointless discussions, then please do so outside of this thread (via e-mail, a private discussion, moderator intervention, whatever).


lakshmikarle, let us know how you are getting on with this. Please ignore anything posted after http:#24821714, as it is not likely to help you with your issue :)
0
 
LVL 40

Expert Comment

by:evilrix
ID: 24822684
>> Even if it was true that the C++ standard doesn't guarantee it (what I don't believe, btw)

When you do...

s = { 0 };

you are implicitly initialising each member (except for the first as that is explicitly initialized to 0). This is NOT a bitwise initialization, it is a member by member initialization so padding remains uninitialized.

From the C standard...

"Each brace-enclosed initializer list has an associated current object. When no
designations are present, subobjects of the current object are initialized in order according
to the type of the current object: array elements in increasing subscript order, structure
members in declaration order, and the first named member of a union. In contrast, a
designation causes the following initializer to begin initialization of the subobject
described by the designator. Initialization then continues forward in order, beginning
with the next subobject after that described by the designator.

Each designator list begins its description with the current object associated with the
closest surrounding brace pair. Each item in the designator list (in order) specifies a
particular member of its current object and changes the current object for the next
designator (if any) to be that member. The current object that results at the end of the
designator list is the subobject to be initialized by the following initializer.

The initialization shall occur in initializer list order, each initializer provided for a
particular subobject overriding any previously listed initializer for the same subobject;
all subobjects that are not initialized explicitly shall be initialized implicitly the same as
objects that have static storage duration"

>> Why do you think you can advice me on what I can assume or not?
There is a stark difference between advice and fact! You cannot make that assumption... fact.
0
 
LVL 40

Expert Comment

by:evilrix
ID: 24822718
Or the shorter version from the C++ standard...

"When an aggregate is initialized the initializer can contain an initializer-clause consisting of a brace enclosed,
comma-separated list of initializer-clauses for the members of the aggregate, written in increasing
subscript or member order. If the aggregate contains subaggregates, this rule applies recursively to the members of the subaggregate"
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24827150
If we read from dangers, it should be real dangers, not phantoms.

All other has only the purpose to denounce another expert's comment without giving any relevant share to the thread.

When I recommend the = { 0 } than it is a good advice. Much better than to not initializing the struct. And better than to using memset. If that recommendation is objected I would expect that the objecter has a concrete sample where it would fail. If that isn't the case but only a hypothetical chance that it might fail for some compilers in future as the standard doesn't rule it, it is most irrelevant to the current case where we have a real compiler and a real problem where all the statements I made easily could be verified that they were true.

>>>> How else would you like me to prove it ?
What about giving a sample where it could fail? You also could have looked at the solaris what happens to structures with or without paddings when using an initializer? Or, you could verify that I was right for the solaris and the compiler you were using. That would have been what I would have expected of a ... friend. Instead you were talking of dangers ...

>>>> You cannot make that assumption... fact.
Is it some juristical terminus? Why can't I make an assumption (it was more a knowledge than an assumption)  if I know it from all my experiences that it is true, now and in future? Infinity made the assumption that the rui was false positive. That might be true but he can't be sure more than - say 80 percent. I was 100 percent sure.

Note, I made no assumptions on the C++ standard (I couldn't do that cause I never studied it) but IMO a compiler ever will make a structure all zero including padding characters even if it was for compatibilty reasons only. If you show me one single evidence for the contrary - any platform, any compiler, any version - I will publicly apologize. But if not, I would expect you to admit that the made objections have no relevance to the question and their solution and were therefore unjustified.

>>>> From the C standard...
>>>> all subobjects that are not initialized explicitly shall be
>>>> initialized implicitly the same as objects that do have static storage duration

@rix
I assume (oh, bad word, right?) you were refering to the above sentence of that paragraph when we speak of the = { 0 } initialization.

You surely will have recognized that it doesn't tell about padding bytes. Maybe we even don't know absolutely that subobjects were (data) members only. In any case, it doesn't tell explicitly that padding bytes may remain unitialized.

So, the statement that the standard doesn't guarantee that padding bytes are zeroed was only reasoned by the fact that this sentence doesn't mention padding at all here. It's not really a strong evidence, isn't it? Can it be that the padding things were mentioned elsewhere in the standard?

Here in that thread we had a structure with two integers. I said, a structure with two integers has no padding bytes. Again, I got the answer I cannot assume that because C++ standard doesn't guarantee that.

We easily can prove that the structure MsgS defined here has no paddings. We easily can prove that setting the structure to zero using the initializer will give all zeros. If proved, all my assumptions are true at least for this platform and this compiler (and my own platform and compiler). And all objections against these comments were unproven, hypothetical and not relevant for solving the question. Period.


>>>> Nothing in that whole quote mentions anything about false positive rui's or padding.

It was the answer to ' why should a consecutive function should care for uninitialized paddings ... '.

Note, telling only the half of the truth and keep the other half secret is the untruth.

>>>> lakshmikarle, let us know how you are getting on with this. Please ignore anything posted after
Are you playing Jackass? You don't play fair.


@lakshmikarle,

I regret that we spoiled your thread.

But IMO the argumentation must be carried on - with you as an unbiased witness - as it is important whether any comment and statement that cannot be guaranteed to be true for ever or at all by the C++ standard, can be denounced as wrong or even dangerous by self-proclaimed guards of the standard as it was done here.

I say there is a C++ before, beside and beyond the C++ standard, which is manifested in millions of projects. I made less than 100 of these projects many of them before there even was a standard. I would like to give my experiences of those projects to you and others without needing to justify each time that all said was guaranteed by the C++ standard.  For questions which do not ask for the standard but refer to a concrete problem on a real system - as it were the overwhelming majority of all questions here in C++ TA - any doubts whether a comment of another expert is valid, should be made for that concrete case and should be proven. To object for the sake of the standard only is off-topic, not helpful and uncooperative.

Note, I wouldn't mind for a FYI comment given. I mean to remember that this kind of putting a controverse opinion to a thread was common practice here in EE. Nowadays, it seems it is usual to hit before and ask later if someone was hurt.


>>>> I'm getting back to trying to help lakshmikarle.

@lakshmikarle,

did you try to change the insert function as suggested by Infinity and me?

I would say that if you omit the construction of the iterator, it is a good chance that the rui wasn't thrown by the dbx.

If so, it is a good solution, not only for test purposes.


 

 
0
 
LVL 1

Author Comment

by:lakshmikarle
ID: 24847685
I tried two other forms of insert as suggested by you which are as follows:

1. if((InfoMap_obj.insert( make_pair(keyVal, info_t ))).second == false );
                {
                        cout<<"\n Element alread exists";
                        return (-1);
                }

2. if ( InfoMap_obj.find(keyVal) != InfoMap_obj.end() )
                {
                        cout<<"\n Element already exists";
                        return (-1);
                }
                InfoMap_obj[keyVal] = info_t;

Above methods are not giving access errors. Moreover, I have performed load testing with the original implementation and it is not giving any problem. So, probably the access error was a 'false positive' as suggested by you.

itsmeandnobodyelse and infinity08,
Thank you very much for  your help
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24847703
You're welcome, lakshmikarle.

Incidentally, which compiler (and version) did you use ? And which version of dbx ?
This might help us to be sure whether it was a false positive or not, rather than just probably.
0
 
LVL 1

Author Comment

by:lakshmikarle
ID: 24847824
Compiler: Sun C++ 5.3
Dbx : 6.2

Thanks,
lakshmikarle
0
 
LVL 53

Accepted Solution

by:
Infinity08 earned 200 total points
ID: 24848504
>> Compiler: Sun C++ 5.3
>> Dbx : 6.2

As old as I suspected ;)

I just remembered that the dbx version I used earlier suppresses rui's by default when the code is not compiled with -g (for debugging symbols), so out of curiosity, I compiled your code on the same platform (Sun Studio 11, dbx 7.5, Sun C++ 5.8), this time with the -g flag, and tested it again, and sure enough, I got the exact same rui report as you.

I also verified that putting it on one line like I suggested earlier :

>> 1) put it on one line :
>>
>>         pair<map<keyType1_t,dataType1_t>::iterator,bool> retItor = InfoMap_obj.insert( pair<keyType1_t, dataType1_t>(keyVal, info_t ) );

does indeed get rid of the rui.
This indicates that the rui is there because of the way the default constructor is implemented for the iterator (inside the pair).

The default constructor for the map iterator shouldn't do anything special, as it basically does the equivalent of initializing a pointer to NULL. So, it's hard to see where a rui could occur, except if it happens due to internal memory copies, in which case it is almost 100% sure that it's a false positive rui.

Of course I don't know how they actually implemented that default constructor, so maybe something is wrong in the STL code.

To summarize, these are the 3 options :

(a) false positive rui - can be ignored, since it's inconsequential
(b) a bug in the compiler and/or STL library - should probably be reported as a bug to Sun, since it apparently has been there from Sun C++ 5.3 through 5.8 at least
(c) a bug in dbx - should probably be reported as a bug to Sun, since it apparently has been there from dbx 6.2 through 7.5 at least

option (c) is not very likely imo. (b) is a bit more likely, but my bets are still on (a).


I'm curious whether putting it on one line, thus avoiding the default constructor (which fixed the problem for me), fixed the problem for you ?
0
 
LVL 40

Expert Comment

by:evilrix
ID: 24848543
Nice work Infinity08.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24848686
>>>> I tried two other forms of insert as suggested by you which are as follows:
The first solution of Infinity08 is faster as it doesn't need to search again when inserting.

The second solution surely is better readable.

You may consider to removing the find completely if it is very unlikely that an already existing key was inserted twice or if in that case the second value should update the previous info_t rather than returning with error. Then you would have

   virtual int insert( keyType1_t keyVal, dataType1_t& info_t)
   {
      InfoMap_obj[keyVal] = info_t;
      return (1);
   };

what either makes an insert or an update.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24848689
And for the record, this sample code causes the same rui :
>more rui.cpp

#include <iostream>

#include <map>
 

int main(void) {

  std::pair<std::map<int, int>::iterator, bool> test;

  std::cout << test.second << std::endl;

  return 0;

}
 

>CC -g rui.cpp

>dbx ./a.out

For information about new features see `help changes'

To remove this message, put `dbxenv suppress_startup_message 7.5' in your .dbxrc

Reading a.out

Reading ld.so.1

Reading libCstd.so.1

Reading libCrun.so.1

Reading libm.so.1

Reading libc.so.1

Reading libdl.so.1

Reading libCstd_isa.so.1

Reading libc_psr.so.1

(dbx) check -access

access checking - ON

(dbx) run

Running: a.out

(process id 5434)

Reading rtcapihook.so

Reading rtcaudit.so

Reading libmapmalloc.so.1

Reading libgen.so.1

Reading rtcboot.so

Reading librtc.so

RTC: Enabling Error Checking...

RTC: Running program...

Read from uninitialized (rui):

Attempting to read 4 bytes at address 0xffbff558

    which is 192 bytes above the current stack pointer

stopped in __rwstd::__rb_tree<int,std::pair<const int,int>,__rwstd::__select1st<std::pair<const int,int>,int>,std::less<int>,std::allocator<std::pair<const int,int> > >::iterator::iterator at 0x000112ec

0x000112ec: iterator+0x0014:    ba,a     0x000447c4     ! 0x447c4

(dbx) where

=>[1] __rwstd::__rb_tree<int,std::pair<const int,int>,__rwstd::__select1st<std::pair<const int,int>,int>,std::less<int>,std::allocator<std::pair<const int,int> > >::iterator::iterator(0xffbff5c4, 0xffbff558, 0xf35d71a8, 0x1, 0x2b100, 0xf3541cb0), at 0x112ec

  [2] std::pair<__rwstd::__rb_tree<int,std::pair<const int,int>,__rwstd::__select1st<std::pair<const int,int>,int>,std::less<int>,std::allocator<std::pair<const int,int> > >::iterator,bool>::pair(this = 0xffbff5c4), line 106 in "utility"

  [3] main(), line 5 in "rui.cpp"

(dbx) exit

>

Open in new window

0
 
LVL 1

Author Closing Comment

by:lakshmikarle
ID: 31601453
Thank infinity and itsmeandnobodyelse for your help.
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Using libpcap/Jpcap to capture and send packets on Solaris version (10/11) Library used: 1.      Libpcap (http://www.tcpdump.org) Version 1.2 2.      Jpcap(http://netresearch.ics.uci.edu/kfujii/Jpcap/doc/index.html) Version 0.6 Prerequisite: 1.      GCC …
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
This video shows how to set up a shell script to accept a positional parameter when called, pass that to a SQL script, accept the output from the statement back and then manipulate it in the Shell.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now