Segfault将一个std :: string复制到另一个?

时间:2013-04-06 15:04:05

标签: c++ oop class scope segmentation-fault

我有以下课程:

class StdinIo : public FileIo{
    public:
             StdinIo();
             ~StdinIo();

             static StdinIo* createObj(const std::string&);
             static bool     checkPath(const std::string&);
    private:
             std::string     tempPath;
             std::string     newPath();
};  

实施1:

StdinIo::StdinIo()
        :FileIo(newPath())
{    
}    
std::string StdinIo::newPath(){
        printf("%s Using FileIo\n", __PRETTY_FUNCTION__);
        std::stringstream tempPathStream;

        tempPathStream << tmpnam(NULL) << getpid();

        tempPathStream.flush();
        const char* szTempPath = tempPathStream.str().c_str();

        FILE *fp=fopen(szTempPath,"wb");
        size_t rv=1;
        char buffer[1024*8];
        if(fp){
                while(rv){
                        rv=fread(buffer,1,sizeof(buffer),stdin);
                        fwrite(buffer,1,rv,fp);
                }
                fclose(fp);
        }
        return tempPathStream.str();
}    

实施2:

StdinIo::StdinIo()
        :FileIo(newPath())
{    
}    
std::string StdinIo::newPath(){
        printf("%s Using FileIo\n", __PRETTY_FUNCTION__);
        std::stringstream tempPathStream;

        tempPathStream << tmpnam(NULL) << getpid();

        tempPathStream.flush();
        tempPath = tempPathStream.str();
        const char* szTempPath = tempPath.c_str();

        FILE *fp=fopen(szTempPath,"wb");
        size_t rv=1;
        char buffer[1024*8];
        if(fp){
                while(rv){
                        rv=fread(buffer,1,sizeof(buffer),stdin);
                        fwrite(buffer,1,rv,fp);
                }
                fclose(fp);
        }
        return tempPath;
  }    

根据我对堆栈的了解,实现1应该给出segFault,而实现2应该不应该。但反过来正在发生。我无法弄清楚原因。

我需要将tempPath字符串作为类成员,以便稍后可以在析构函数中删除该文件。

StdinIo::~StdinIo(){
      if( unlink(tempPath.c_str()) != 0 )
              perror( "Error deleting file" );
}

在这里和那里注释出行之后,我发现在以下行发生了seg-fault:

 tempPath = tempPathStream.str();

gdb说:

 Program received signal SIGSEGV, Segmentation fault.
 __exchange_and_add_dispatch (__mem=0xfffffffffffffff8, __val=<optimized out>)
     at /usr/src/debug/gcc-4.7.2-20120921/obj-x86_64-redhat-linux/x86_64-redhat-          linux/libstdc++-v3/include/ext/atomicity.h:83
 83       return __exchange_and_add_single(__mem, __val);

1 个答案:

答案 0 :(得分:1)

您的第二个实现调用newPath()并在对象完全初始化之前访问tempPath(将其传递给基类构造函数)。这会导致未定义的行为。

如果您绝对需要文件名的本地副本而不对现有代码进行重大更改,则可以使用实现#1来执行此类操作。

class StdIoSpecialData : public FileIo
{
protected:

    StdIoSpecialData(const std::string &fname)
        : FileIo(fname),
          tempPath(fname)
    {
    }
    const std::string tempPath;
};

class StdIo : public StdIoSpecialData
{
public:
    StdIo()
       : StdIoSpecialData(newPath())
    {
    }
};