简体   繁体   English

stringstream溢出4GB

[英]stringstream overflow at 4GB

I'm having trouble getting beyond 4GB limitation for stringstream, even though it is running on a 64bit linux box with enough memory. 即使它运行在具有足够内存的64位Linux机器上,我也无法超越4GB的stringstream限制。

The test code below (revised after reading your comments) core dump after 4GB. 下面的测试代码(阅读你的评论后修改)4GB之后的核心转储。

From the gdb trace, stringstream uses the default std::char_traits where int_type is set to 32bit int, rather than 64bit size_t. 在gdb跟踪中,stringstream使用默认的std :: char_traits,其中int_type设置为32bit int,而不是64bit size_t。 Any suggestion to work around? 有什么建议可以解决吗?

#include <stdint.h>
#include <iostream>
#include <sstream>
#include <math.h>
using namespace std;

int main(int narg, char** argv)
{
    string str;
    stringstream ss;
    const size_t GB = (size_t)pow(2, 30);

    str.resize(GB, '1');
    cerr << "1GB=" << str.size()
             << ", string::max_size=" << str.max_size()/GB << "GB"
             << ", sizeof(int)=" << sizeof(int)
             << ", sizeof(int64_t)=" << sizeof(int64_t)
             << ", sizeof(size_t)=" << sizeof(size_t)
             << endl;
    string().swap(str);

    str.resize(6*GB, '6');
    cerr << "str.size()=" << (str.size() / GB) << "GB allocated successfully"
            << ", ended with " << str.substr(str.size()-5, 5) << endl;
    string().swap(str);

    str.resize(GB/4, 'Q');
    cerr << "writing to stringstream..." << std::flush;
    for (int i = 0; i < 30; ++i) {
        ss << str << endl;
        cerr << double(ss.str().size())/GB << "GB " << std::flush;
    }
    cerr << endl;
    exit(0);
}

The output is: 输出是:

1GB=1073741824, string::max_size=4294967295GB, sizeof(int)=4, sizeof(int64_t)=8, sizeof(size_t)=8
str.size()=6GB allocated successfully, ended with 66666
writing to stringstream...0.25GB 0.5GB 0.75GB 1GB 1.25GB 1.5GB 1.75GB 2GB 2.25GB 2.5GB 2.75GB 3GB 3.25GB 3.5GB 3.75GB Segmentation fault (core dumped)

The gdb stack trace is: gdb堆栈跟踪是:

(gdb) where
#0  0x00002aaaaad5e0c1 in std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::overflow(int) () from /usr/lib64/libstdc++.so.6
#1  0x00002aaaaad62cbd in std::basic_streambuf<char, std::char_traits<char> >::xsputn(char const*, long) () from /usr/lib64/libstdc++.so.6
#2  0x00002aaaaad5657d in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) () from /usr/lib64/libstdc++.so.6
#3  0x000000000040112b in main ()

The binary seems to be 64bits. 二进制文件似乎是64位。

$ file a.out
a.out: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped

Nick, good point on checking the preprocessor output. 尼克,检查预处理器输出的好点。 Somehow std::char_straits overwrites __gnu_cxx::char_straits, and redefines int_type to be int, rather than unsigned long as in __gnu_cxx::char_straits. 某种程度上std :: char_straits会覆盖__gnu_cxx :: char_straits,并将int_type重新定义为int,而不是像__gnu_cxx :: char_straits那样重新定义无符号长整数。 This is very surprising! 这非常令人惊讶!

namespace __gnu_cxx
{
# 61 "/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/char_traits.h" 3
  template <class _CharT>
    struct _Char_types
    {
      typedef unsigned long int_type;
      typedef std::streampos pos_type;
      typedef std::streamoff off_type;
      typedef std::mbstate_t state_type;
    };
# 86 "/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/char_traits.h" 3
  template<typename _CharT>
    struct char_traits
    {
      typedef _CharT char_type;
      typedef typename _Char_types<_CharT>::int_type int_type;
      typedef typename _Char_types<_CharT>::pos_type pos_type;
      typedef typename _Char_types<_CharT>::off_type off_type;
      typedef typename _Char_types<_CharT>::state_type state_type;
              ....
               };

namespace std
{
# 224 "/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/char_traits.h" 3
  template<class _CharT>
    struct char_traits : public __gnu_cxx::char_traits<_CharT>
    { };



  template<>
    struct char_traits<char>
    {
      typedef char char_type;
      typedef int int_type;
      typedef streampos pos_type;
      typedef streamoff off_type;
      typedef mbstate_t state_type;
              ...
              };

EDIT: below from the STL website http://www.cplusplus.com/reference/string/char_traits/ where char_traits specialization uses int. 编辑:以下来自STL网站http://www.cplusplus.com/reference/string/char_traits/其中char_traits specialization使用int。

typedef INT_T int_type; 
Where INT_T is a type that can represent all the valid characters representable by a    char_type plus an end-of-file value (eof) which is compatible with iostream class member functions.
For char_traits<char> this is int, and for char_traits<wchar_t> this is wint_t 

Can you post a preprocessed source file. 你可以发布一个预处理的源文件。

Reference to _Char_types removed because it was misleading. 删除了对_Char_types引用,因为它具有误导性。

I'm not sure the int_type is related, the specialisation for char does indeed use int for int_type. 我不确定int_type是否相关,char的特化确实对int_type使用int。

int_type is a typedef to hold an individual character (ie at least one byte for ascii, higher for wchar_t). int_type是一个用于保存单个字符的typedef(即ascii至少为一个字节,对于wchar_t为至少一个字节)。 It is not used to store a range of characters (see std::streamoff below). 它不用于存储一系列字符(请参阅下面的std :: streamoff)。


From your preprocessed output I suspect that std::streamoff could be the culprit. 从你的预处理输出我怀疑std :: streamoff可能是罪魁祸首。 From the headers on my system: 从我系统上的标题:

# 90 "/usr/include/c++/4.6/bits/postypes.h" 3
  typedef long streamoff;

std::streamoff is used in std::streampos which if defined incorrectly I think would lead to the stringstream calling the overflow function. std :: streamoff用于std :: streampos,如果定义不正确,我认为会导致stringstream调用overflow函数。

Have you checked that the correct headers are included? 你检查过包含了正确的标题吗?

# 61 "/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/char_traits.h" 3

Is the following path: 是以下路径:

/usr/include/c++/4.1.2/bits/char_traits.h

-nick -缺口

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM