This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

libstdc++/2773: "allocator" not used by stringstream!



>Number:         2773
>Category:       libstdc++
>Synopsis:       "allocator" not used by stringstream!
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue May 08 07:26:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Carlo Wood
>Release:        gcc version 3.0 20010423 (prerelease)
>Organization:
>Environment:
i686-pc-linux-gnu
>Description:
To my surprice I found that stringstream (etc) calls
directly malloc/free instead of Allocator::allocate()
as it should.

Consider the following test program:

----------------------------------------------------------
#include <new>
#include <cstdlib>
#define _GLIBCPP_FULLY_COMPLIANT_HEADERS
#include <sstream>
#include <iostream>
 
#include <unistd.h>     // Needed for 'write'
static bool start = false;
#define print(x) if (start) write(1, x, sizeof(x));
 
void* operator new(size_t size)
{
  print("Calling new\n");
  return malloc(size);
}
 
void* operator new[](size_t size)
{
  print("Calling new[]\n");
  return malloc(size);
}
 
void operator delete(void* ptr)
{
  print("Calling delete\n");
  free(ptr);
}
 
void operator delete[](void* ptr)
{
  print("Calling delete[]\n");
  free(ptr);
}
 
class my_allocator : public std::allocator<char> {
public:
  pointer allocate(size_type size, std::allocator<void>::const_pointer hint = 0)
  {
    print("Calling allocate\n");
    return new char [size];
  }
  void deallocate(pointer p, size_type)
  {
    print("Calling deallocate\n");
    delete [] p;
  }
};
 
typedef std::basic_stringstream<char, std::char_traits<char>, my_allocator> my_stringstream;
 
size_t size;
 
void test(void)
{
  my_stringstream ss;
  print("Writing 12 characters to stringstream:\n");
  ss << "Test " << 123456 << '\n';
  print("Writing 10000013 characters to stringstream:\n");
  for (int i = 0; i < 100000; ++i)
    ss << "01234567890123456789012345678901234567890123456789012345678901234567890123456789012  ss << "Test " << 123.456 << '\n';
  print("Done writing to stringstream.\n");
  size = ss.rdbuf()->pubseekoff(0, std::ios_base::cur, std::ios_base::out) -
         ss.rdbuf()->pubseekoff(0, std::ios_base::cur, std::ios_base::in);
  print("Destructing stringstream object\n");
}
 
int main(void)
{
  start = true;
  print("Start test\n");
  new char [10];
  test();
  print("End test\n");
  start = false;
  std::cout << "Size of stringstream buffer was: " << size << '\n';
  return 0;
}
-------------------------------------------------------

The output of this program is:

Start test
Calling new[]
Calling new
Writing 12 characters to stringstream:
Calling new
Calling new
Writing 10000013 characters to stringstream:
Done writing to stringstream.
Destructing stringstream object
Calling delete
Calling delete
Calling delete
End test
Size of stringstream buffer was: 10000025


Prove that the buffer of over 10 Mb was allocated with
malloc was found by linking with a malloc library that
prints every call to malloc/free, then the output is:

[Calling malloc(112) = 0x805491a][Calling malloc(36) = 0x8054990][Calling malloc(14) = 0x80549ba][Calling malloc(12) = 0x80549ce][Calling malloc(52) = 0x80549e0][Calling malloc(8) = 0x8054a1a][Calling malloc(28) = 0x8054a2c][Calling malloc(8) = 0x8054a4e][Calling malloc(40) = 0x8054a60][Calling malloc(13) = 0x8054a8e][Calling malloc(40) = 0x8054aa0][Calling malloc(8) = 0x8054ace][Calling malloc(8) = 0x8054ae0][Calling malloc(24) = 0x8054af2][Calling malloc(13) = 0x8054b10][Calling malloc(17) = 0x8054b22][Calling malloc(18) = 0x8054b38][Calling malloc(8) = 0x8054b50][Calling malloc(8) = 0x8054b62][Calling malloc(16) = 0x8054b74][Calling malloc(8) = 0x8054b8a][Calling malloc(8) = 0x8054b9c][Calling malloc(104) = 0x8054bae][Calling free(0x80549e0)][Calling malloc(4)[Calling free(0x80549f2)] = 0x80549e0][Calling malloc(12)[Calling free(0x8054a04)] = 0x80549f2][Calling malloc(364) = 0x8054c1c][Calling malloc(8192) = 0x8054d8e][Calling malloc(1) = 0x8054a04][Calling malloc(112) = 0x8056d94][Calling malloc(12) = 0x8056e0a][Calling malloc(364) = 0x8056e1c][Calling malloc(8192) = 0x8056f8e][Calling malloc(1) = 0x8058f94][Calling malloc(112) = 0x8058fa6][Calling malloc(12) = 0x805901c][Calling malloc(364) = 0x805902e][Calling malloc(8192) = 0x80591a0][Calling malloc(1) = 0x805b1a6]Start test
Calling new[]
[Calling malloc(10) = 0x805b1b8]Calling new
[Calling malloc(84) = 0x805b1ca]Writing 12 characters to stringstream:
[Calling malloc(1037) = 0x805b224]Calling new
[Calling malloc(20) = 0x805b636][Calling malloc(17) = 0x805b650][Calling malloc(18) = 0x805b666]Calling new
[Calling malloc(16) = 0x805b67e]Writing 10000013 characters to stringstream:
[Calling malloc(1037) = 0x805b694][Calling free(0x805b224)][Calling malloc(2061) = 0x805baa6][Calling free(0x805b694)][Calling malloc(2061) = 0x805c2b8][Calling free(0x805baa6)][Calling malloc(4109) = 0x805caca][Calling free(0x805c2b8)][Calling malloc(4109)[Calling free(0x805c6a6)] = 0x805b694][Calling free(0x805caca)][Calling malloc(8205) = 0x805c6a6][Calling free(0x805b694)][Calling malloc(8205) = 0x805e6b8][Calling free(0x805c6a6)][Calling malloc(16397) = 0x80606ca][Calling free(0x805e6b8)][Calling malloc(16397)[Calling free(0x805f6a6)] = 0x805b694][Calling free(0x80606ca)][Calling malloc(32781) = 0x805f6a6][Calling free(0x805b694)][Calling malloc(32781) = 0x80676b8][Calling free(0x805f6a6)][Calling malloc(65549) = 0x806f6ca][Calling free(0x80676b8)][Calling malloc(65549)[Calling free(0x806b6a6)] = 0x805b694][Calling free(0x806f6ca)][Calling malloc(131085) = 0x806b6a6][Calling free(0x805b694)][Calling malloc(131085) = 0x808b6b8][Calling free(0x806b6a6)][Calling malloc(262157) = 0x80ab6ca][Calling free(0x808b6b8)][Calling malloc(262157)[Calling free(0x809b6a6)] = 0x805b694][Calling free(0x80ab6ca)][Calling malloc(524301) = 0x809b6a6][Calling free(0x805b694)][Calling malloc(524301) = 0x811b6b8][Calling free(0x809b6a6)][Calling malloc(1048589) = 0x819b6ca][Calling free(0x811b6b8)][Calling malloc(1048589)[Calling free(0x815b6a6)] = 0x805b694][Calling free(0x819b6ca)][Calling malloc(2097165) = 0x815b6a6][Calling free(0x805b694)][Calling malloc(2097165) = 0x835b6b8][Calling free(0x815b6a6)][Calling malloc(4194317) = 0x855b6ca][Calling free(0x835b6b8)][Calling malloc(4194317)[Calling free(0x845b6a6)] = 0x805b694][Calling free(0x855b6ca)][Calling malloc(8388621) = 0x845b6a6][Calling free(0x805b694)][Calling malloc(8388621) = 0x8c5b6b8][Calling free(0x845b6a6)][Calling malloc(16777229) = 0x945b6ca][Calling free(0x8c5b6b8)]Done writing to stringstream.
Destructing stringstream object
[Calling free(0x945b6ca)]Calling delete
[Calling free(0x805b1ca)][Calling free(0x805b666)][Calling free(0x805b650)]Calling delete
[Calling free(0x805b636)]Calling delete
[Calling free(0x805b67e)]End test
[Calling malloc(20)[Calling free(0x805b1e4)] = 0x805b1ca][Calling malloc(17)[Calling free(0x805b1fa)] = 0x805b1e4][Calling malloc(18)[Calling free(0x805b212)] = 0x805b1fa][Calling malloc(16)[Calling free(0x805b228)] = 0x805b212]Size of stringstream buffer was: 10000025
[Calling free(0x8054d8e)][Calling free(0x8054a04)][Calling free(0x8054c1c)][Calling free(0x80549f2)][Calling free(0x805491a)][Calling free(0x8056f8e)][Calling free(0x8058f94)][Calling free(0x8056e1c)][Calling free(0x8056e0a)][Calling free(0x8056d94)][Calling free(0x80591a0)][Calling free(0x805b1a6)][Calling free(0x805902e)][Calling free(0x805901c)][Calling free(0x8058fa6)]

Is there any reason for not supporting an allocator?
Or is this really an (unintentional) bug?
>How-To-Repeat:

>Fix:

>Release-Note:
>Audit-Trail:
>Unformatted:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]