The remove() behavior of container list on MAC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// My code is bellowing:
	  class MyClass{
	  public:
		  MyClass(int key):fKey(key) {}
		  const int GetKey() const { return fKey; }
		  // some other members 
	  private:		  
		  int fKey;
	  };

	  bool operator==(const MyClass& lh, const MyClass& rh)
	  {
		  cout<<lh.GetKey()<<"  "<<rh.GetKey()<<endl;
          return (lh.GetKey() == rh.GetKey());
	  }

	  list<MyClass> myList;
	  // insert some items into myList. The items are with key 1, 2, 3, 4 and 5
	  MyClass val(3);
	  cout<<"Before remove"<<endl;
	  myList.remove(val);
	  cout<<"After remove"<<endl;

//------------------- The source code of list::remove() in MAC sdk 10.4 
    template<typename _Tp, typename _Alloc>
    void
    list<_Tp, _Alloc>::
    remove(const value_type& __value)
    {
      iterator __first = begin();
      iterator __last = end();
      while (__first != __last)
	{
	  iterator __next = __first;
	  ++__next;
	  if (*__first == __value)
	    _M_erase(__first);
	  __first = __next;
	}
    }

	// Erases element at position given.
      void
      _M_erase(iterator __position)
      {
        __position._M_node->unhook();
        _Node* __n = static_cast<_Node*>(__position._M_node);
        this->get_allocator().destroy(&__n->_M_data);
        _M_put_node(__n);
      }


//====================================

My questing is whether it is possible that the value of "__value" might be changed in list::remove()?
I got a strange problem, it might remove 2 items from myList in only one statement "myList.remove(val);".
The log looks like:

        Before remove
	1  3
	2  3
	3  3
	4  4
	5  4
	After remove
        


The issue is at the line "4 4", does anybody have any idea what happend?

My guess is the statement in list::remove() "_M_erase(__first);" might release or delete the object that __first is pointing to,
and which just is __value. I mean the object __value is not really existed any more after the statement. Is that possible?

Did i miss something? Or there is any rule i need to follow while using container list on MAC?

PS:
The code i posted is just a sample. In my real project, a customized type is used but not "int".
Last edited on
I think i have got the reason, let's see the source code on Windows from MS vc++.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void remove(const _Ty& _Val_arg)
{	// erase each element matching _Val
/* Dinkumware makes a copy of _Val_arg in case it's removed along the way, i.e.
* when the user pass an element of the list as _Val_arg.
*
* We believe that the signature of std::list::remove should be changed
* from remove(const _Ty&) to remove(_Ty) to explicitly indicate that a copy is involved.
*/
const _Ty _Val = _Val_arg;	// in case it's removed along the way
iterator _Last = end();
for (iterator _First = begin(); _First != _Last; )
if (*_First == _Val)
_First = erase(_First);
else
++_First;
}

Please pay attention to statement "const _Ty _Val = _Val_arg;" ant its comment.
The problem i faced is, the argument that passed into list::remove() is the object from list.
That means on MAC, the statement "_M_erase(__first);" would destroy the object __first pointing to, unfortunately, __first is pointing to __value.
Therefore, after "_M_erase(__first);", the __value is destroyed. Make a copy to be the argument to remove items from list is the solution.
Topic archived. No new replies allowed.