我有以下类(class):
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 应该给出段错误,而实现 2 不应该。但相反的情况正在发生。我不知道为什么。
我需要 tempPath 字符串作为类成员,以便稍后在析构函数中删除文件。
StdinIo::~StdinIo(){
if( unlink(tempPath.c_str()) != 0 )
perror( "Error deleting file" );
}
注释掉这里那里的行后,我发现在下面的行中,发生了段错误:
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);
最佳答案
在对象完全初始化之前,您的第二个实现调用 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())
{
}
};
关于c++ - 将一个 std::string 复制到另一个时出现段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15852459/