将字符串流定义为标头中的成员时发生Malloc错误

Malloc error when defining stringstream as member in header

本文关键字:成员 错误 Malloc 字符串 定义      更新时间:2023-10-16

所以我有了这个类:

/** Controller.h before editing **/
namespace base
{
    class Controller
    {
        private:
            std::string* errorText;
            std::string fileIdentifier;
            bool isFileIdentifierSet;
            bool isFileChecked;
            bool isFileParsed;
            bool isNddlGenerated;
        public:
            /** public stuff... **/
    }
}

到目前为止,这个类的实现是有效的,但后来我不得不使用一个库,它产生了很多cerr输出,但由于这是一个CLI程序,我想捕捉错误文本并以我想要的方式显示它们。所以我在So中搜索cerr抑制,发现了很多好的提示,我当时想实现这些提示。请注意,在我添加库后,程序确实工作了,我只是对库产生的错误输出不满意。所以这是上面类的更新版本:

/** Controller.h after editing **/
namespace base
{
    class Controller
    {
        private:
            std::stringstream cerrOvRdBuf; /** new **/ /** error **/
            std::streambuf* cerrStdRdBuf; /** new **/
            std::string* errorText;
            std::string fileIdentifier;
            bool isFileIdentifierSet;
            bool isFileChecked;
            bool isFileParsed;
            bool isNddlGenerated;
            void disableCerr(); /** new **/
            void enableCerr(); /** new **/
            std::string getBufferedCerrOutput(); /** new **/
        public:
            /** public stuff... **/
    }
}

功能的实现是这样的:

/** Implementation of new functions in Controller.cpp **/
void Controller::disableCerr()
{
    std::cerr.rdbuf(this->cerrOvRdBuf.rdbuf());
}
void Controller::enableCerr()
{
    std::cerr.rdbuf(this->cerrStdRdBuf);
}
string Controller::getBufferedCerrOutput()
{
    return this->cerrOvRdBuf.str();
}

然而,即使我甚至不使用任何函数,程序也会因以下输出而崩溃:

nddl-generator-cli: malloc.c:2373: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1)) & ~((2 *(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long) old_end & pagemask) == 0)' failed.
Aborted (core dumped)

然后,我继续删除所有内容,直到我看到错误的确切原因,最后我意外地发现,一旦我在Controller.h中定义了私有成员std::stringstream cerrOvRdBuf;(我用注释/** error **/标记了上面的定义(,错误就会发生。是什么导致了这些问题?我无法想象一个简单的成员定义会导致程序崩溃?

我的意图是在进行库调用时立即使用这些函数,比如:

/** inside any function of Controller.cpp **/
this->disableCerr();
/** any library call **/
this->enableCerr();
string errorFromLib = this->getBufferedCerrOutput();
/** go on normally, print erros the way I want, etc... **/

总之,这是我必须对Controller.h(Controller.cpp中没有任何内容(进行的最小更改,以再现崩溃:

/** Controller.h with minimum changes producing the error **/
namespace base
{
    class Controller
    {
        private:
            std::stringstream cerrOvRdBuf; /** new **/ /** error **/
            std::string* errorText;
            std::string fileIdentifier;
            bool isFileIdentifierSet;
            bool isFileChecked;
            bool isFileParsed;
            bool isNddlGenerated;
            /** please note that the functions are not even defined or implemented here **/
        public:
            /** public stuff... **/
    }
}

使用std::stringstream作为类成员是完全有效的。通常,当您添加新成员并出现一些神秘的错误或崩溃时,这是由于需要重新编译依赖的源代码。尝试执行make clean,然后重建所有内容。


除此之外,您必须保存旧的流缓冲区,否则以后无法恢复它。更改

void Controller::disableCerr()
{
    std::cerr.rdbuf(this->cerrOvRdBuf.rdbuf());
}

void Controller::disableCerr()
{
    cerrStdRdBuf = std::cerr.rdbuf(this->cerrOvRdBuf.rdbuf());
}