1

我有以下课程:

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);
4

1 回答 1

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())
    {
    }
};
于 2013-04-06T15:14:01.353 回答