Bug 16882 - Memory leak with g++ 2.8.1 and STL 2.8.1.1 list / map
Summary: Memory leak with g++ 2.8.1 and STL 2.8.1.1 list / map
Status: Closed FIXED
Alias: None
Product: Ports & Packages
Classification: Unclassified
Component: Individual Port(s) (show other bugs)
Version: Latest
Hardware: Any Any
: Normal Affects Only Me
Assignee: David E. O'Brien
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2000-02-21 16:40 UTC by hostetlb
Modified: 2000-11-11 06:38 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description hostetlb 2000-02-21 16:40:00 UTC
We have discovered a memory leak problem using FreeBSD 2.2.8, g++ version
2.8.1, and GNU STL libraries (libstdc++) version 2.8.1.1.  We are also using
the gcc28 patches provided by the FreeBSD web-site.

The problem appears when you have two C++ files sharing an STL list, set /
multiset or map / multimap.  There is actually a larger problem with static
variables in template classes, but the STL objects are the easiest way to
produce this problem. 

One of the files inserts entries into the list (causing memory allocation),
while the other file releases the entries from the list (returning the memory
to an STL allocator).  Examining the assembler file created for the two
objects, we saw ".weak" definitions for the STL allocator's free_list (among
many other weak definitions), which we would expect the linker to combine into
a single actual location in the final executable.  Even running "nm" on the
final executable only shows one free_list variable.  However, using gdb to
step through the code, and examining where the allocation and deallocation
routines were actually accessing the free_list showed that the linker had
actually kept each free_list, and all references to each was kept local within
each object file.  This caused one STL allocator to continually go to the OS
to get memory to add to the list, while another STL allocator was releasing
those blocks back into its own private buffer.

Fix: 

We were able to work around this problem by patching the gcc28 patches.  We
removed the following patch from "patch-01", which has the effect of disabling
gcc's use of weak variable declarations :

+
+#define ASM_WEAKEN_LABEL(FILE,NAME) \
+  do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
+  fputc ('\n', FILE); } while (0)
+

After applying this patch and recompiling, only one free_list exists in the
executable, and the memory leak goes away.
How-To-Repeat: The following code can be used to produce the problem.

1. Compile it using "g++ -o leak *.C"

2. Start "top" in a separate window.

3. Run "leak", and watch the size of the process grow through each iteration.


-- file : header.H --

#ifndef __header_H
#define __header_H

#include <list>

typedef list<int> IntList;

void producer(IntList &l);
void consumer();

#endif


-- file : consumer.C --

#include "header.H"
#include <unistd.h>
#include <stdio.h>

main()
{
    for (int i = 0; i < 20; i++) {
        IntList l;
        producer(l);
        l.clear();
        printf("Done with pass %d\n", i+1);
        sleep(1);
    }
}


-- file : producer.C --

#include "header.H"

// Simply adds list_size entries to the list.  The caller will release them
void producer(IntList &l)
{
    for (int i = 0; i < 100000; i++) {
        l.push_back(1);
    }
}
Comment 1 cpiazza freebsd_committer freebsd_triage 2000-02-21 23:25:54 UTC
Responsible Changed
From-To: freebsd-ports->obrien

Over to maintainer 

Comment 2 David O'Brien 2000-02-29 09:14:50 UTC
I am not sure what to do about this... some software depends on weak
symbol support.  :-(

-- 
-- David    (obrien@NUXI.com)
Comment 3 David E. O'Brien freebsd_committer freebsd_triage 2000-11-11 06:37:13 UTC
State Changed
From-To: open->closed

Commited.