在使用自定义语言环境填充stringstream时的Segfault

时间:2014-03-25 22:24:32

标签: c++ memory-management locale stringstream

基于如何使用逗号格式化数字的问题的答案here,我使用以下代码:

#include <locale>
#include <stringstream>

namespace
{

class comma_numpunct : public std::numpunct<char>
{
  protected:
    virtual char do_thousands_sep() const
    {
        return ',';
    }

    virtual std::string do_grouping() const
    {
        return "\03";
    }
};

}


/* Convert number to string using a comma as the thousands separator. */
string thousands(const int x) {

    /* custom locale to ensure thousands separator is comma */
    comma_numpunct* comma_numpunct_ptr = new comma_numpunct();
    std::locale comma_locale(std::locale(), comma_numpunct_ptr);

    stringstream ss;
    ss.imbue(comma_locale); // apply locale to stringstream
    ss << x;

    /* garbage collection */
    delete comma_numpunct_ptr;

    return ss.str();
}

GDB提供以下回溯:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000021 in ?? ()
(gdb) bt
#0  0x0000000000000021 in ?? ()
#1  0x00007ffff7701535 in std::locale::_Impl::~_Impl() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2  0x00007ffff770166d in std::locale::~locale() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x000000000044b93e in thousands (x=358799) at ../globals_utilities.cpp:104
#4  0x000000000045650d in main (argc=1, argv=0x7fffffffdf58) at ../main.cpp:67

所以,问题是(我相信)我试图释放new'内存。但我不知道如何解决这个问题。 (我不能使用std::unique_ptr,因为我并不总是使用C ++ 11支持进行编译。)

如何在不泄漏内存的情况下修复段错误?

1 个答案:

答案 0 :(得分:2)

您的问题是区域设置方面(numpunct)。如果通过构造函数将其传递给区域设置,并且构面的引用为零,则区域设置将删除构面。

您可以这样做:

comma_numpunct(size_t refs = 0)
:   numpunct(refs)
{}

comma_numpunct* comma_numpunct_ptr = new comma_numpunct(1);

或更好地省略:

// double delete
// delete comma_numpunct_ptr;

您可以省略facet的分配:

string thousands(const int x) {
   comma_numpunct numpunct(1);
   std::locale comma_locale(std::locale(), &numpunct);
   std::stringstream ss;
   ss.imbue(comma_locale);
   ss << x;
   return ss.str();
}

从22.3.1.1.2类locale :: facet

  

构造函数的refs参数用于生命周期管理。

     

- 对于refs == 0,实现执行delete   static_cast(f)(其中f是指向构面的指针)   当包含facet的最后一个locale对象被销毁时;对于   refs == 1,实现永远不会破坏方面。