From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15705 invoked by alias); 7 Feb 2007 16:46:50 -0000 Received: (qmail 15633 invoked by uid 48); 7 Feb 2007 16:46:33 -0000 Date: Wed, 07 Feb 2007 16:46:00 -0000 Message-ID: <20070207164633.15632.qmail@sourceware.org> X-Bugzilla-Reason: CC References: Subject: [Bug libstdc++/17012] [DR 526] std::list's function, remove, looks like it is reading memory that has been freed. In-Reply-To: Reply-To: gcc-bugzilla@gcc.gnu.org To: gcc-bugs@gcc.gnu.org From: "hhinnant at apple dot com" Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2007-02/txt/msg00881.txt.bz2 ------- Comment #12 from hhinnant at apple dot com 2007-02-07 16:46 ------- At the ad-hoc LWG meeting in Batavia, Jan 22-24, 2007, the LWG decided that self referencing code in list::remove must work. Here is a preview of the issue which is currently set to become official at the Spring '07 meeting: http://home.twcny.rr.com/hinnant/cpp_extensions/issues_preview/lwg-active.html#526 Here is a patch to mainline to make it work. I believe the approach taken by this patch is superior to copying the value as it currently looks like a future standard will not require that the value_type be copyable. Additionally the cost of copying the value_type can be arbitrarily large. If we have a utility similar to boost::address_of, that might be better than using operator& to get the address of the value_type (to accommodate types which overload operator&). Index: libstdc++-v3/include/bits/list.tcc =================================================================== --- libstdc++-v3/include/bits/list.tcc (revision 121691) +++ libstdc++-v3/include/bits/list.tcc (working copy) @@ -176,14 +176,22 @@ { iterator __first = begin(); iterator __last = end(); + iterator __extra = __last; while (__first != __last) { iterator __next = __first; ++__next; if (*__first == __value) - _M_erase(__first); + { + if (&__value != &*__first) + _M_erase(__first); + else + __extra = __first; + } __first = __next; } + if (__extra != __last) + _M_erase(__extra); } template -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17012