From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20692 invoked by alias); 12 Oct 2004 16:29:41 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Received: (qmail 20651 invoked by alias); 12 Oct 2004 16:29:38 -0000 Date: Tue, 12 Oct 2004 16:29:00 -0000 From: "gcc-bugzilla at gcc dot gnu dot org" To: gcc-bugs@gcc.gnu.org Message-ID: <20041012162922.17948.snyder@fnal.gov> Reply-To: gcc-bugzilla@gcc.gnu.org Subject: [Bug libstdc++/17948] New: iterator increment bug in _Rb_tree::erase(it,it) X-Bugzilla-Reason: CC X-SW-Source: 2004-10/txt/msg01613.txt.bz2 List-Id: I expect the following program to produce the following output: a 2 b 1 1 i.e, two elements go into the set, we delete one, and one remains. However, when i compile this with the current cvs head, the program actually does the following: $ g++ -g -o x x.cc $ ./x a 2 b 0 1 $ i.e., two elements go in, take away one, and none are left. Someone's arithmetic is bad... It looks like the problem is in this function in stl_tree.h: template void _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: erase(iterator __first, iterator __last) { if (__first == begin() && __last == end()) clear(); else for (; __first != __last; ++__first) erase(__first); } Note that in the loop, the iterator __first is referenced in the increment _after_ it has been erased from the container --- which is undefined behavior. Below is an attempt to fix this. With this patch, the test behaves as expected. Environment: System: Linux karma 2.6.8.1 #20 Mon Sep 13 23:48:47 EDT 2004 i686 i686 i386 GNU/Linux Architecture: i686 host: i686-pc-linux-gnu build: i686-pc-linux-gnu target: i686-pc-linux-gnu configured with: /home/sss/gcc/gcc/configure --prefix=/usr/local/gcc --enable-threads=posix --enable-long-long --enable-languages=c,c++,f95 How-To-Repeat: ------------------------------------------- #include void test2 () { std::set s; s.insert(2); s.insert(3); printf ("a %d\n", s.size()); int x = s.erase (3); printf ("b %d %d\n", s.size(), x); } int main () { test2 (); return 0; } ------------------------------------------- ------- Additional Comments From snyder at fnal dot gov 2004-10-12 16:29 ------- Fix: 2004-10-11 scott snyder * include/bits/stl_tree.h (erase(iterator,iterator)): Fix iterator loop. --- libstdc++-v3/include/bits/stl_tree.h-orig 2004-10-11 23:17:30.096014584 -0400 +++ libstdc++-v3/include/bits/stl_tree.h 2004-10-11 23:19:39.688313560 -0400 @@ -1087,8 +1087,12 @@ if (__first == begin() && __last == end()) clear(); else - for (; __first != __last; ++__first) + for (iterator __next = __first; __first != __last; __first = __next) + { + ++__next; erase(__first); + } + } template