【发布时间】:2013-05-28 08:49:03
【问题描述】:
我想做类似的事情
FileIn::FileIn(const char* filename)
{
handle=CreateFile(filename,GENERIC_READ,FILE_SHARE_READ
,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(handle==INVALID_HANDLE_VALUE)
{
// Base class ExceptionWinapi will call GetLastError();
throw ExceptionWinapiFile(filename);
}
}
但是,如果 ExceptionWinapi 不复制文件名,则在捕获异常时它可能会无效。但是复制文件名需要 malloc(如果缓冲区不是固定长度),这可能会失败。那么字符串存放在哪里呢?
编辑:为了更清楚,请考虑
#include <cstdio>
class Foo
{
public:
Foo(const Foo& foo){printf("Foo copy\n");}
Foo(){printf("Foo\n");}
~Foo(){printf("~Foo\n");}
};
class TestExcep
{
public:
TestExcep(const Foo& bar):m_bar(bar){}
private:
Foo m_bar;
};
class Test
{
public:
Test(const Foo& bar)
{throw TestExcep(bar);}
};
int main()
{
try
{
Foo bar;
Test a(bar);
}
catch(const TestExcep& excep)
{
printf("Error\n");
return 1;
}
return 0;
}
打印(添加评论)
Foo
Foo copy
~Foo <======Destroy old Foo after copy to the exception object!
Error
~Foo
编辑 2:如果 Foo(const Foo& foo){printf("Foo copy\n");} 抛出,那么就是那个异常不是旧的异常。这也很糟糕。
编辑 3:
ExceptionWinapiFile 的有用部分
ExceptionWinapiFile(const char* filename)
{
m_length=streln(filename)+1;
m_buffer=(char*)malloc(m_length*sizeof(char));
if(m_buffer==NULL)
{
//The problem
abort(); //????
}
memcpy(m_buffer,filename,m_length*sizeof(char));
}
还有(又是同样的问题)
ExceptionWinapiFile(const ExceptionWinapiFile& e)
{
m_length=e.m_length;
m_buffer=(char*)malloc(m_length*sizeof(char));
if(m_buffer==NULL)
{
//The problem
abort(); //????
}
memcpy(m_buffer,e.filename,m_length*sizeof(char));
}
至少在 dtor 中没有问题:
~ExceptionWinapiFile()
{
free(m_buffer);
m_buffer=NULL; //As recommended by boost
}
【问题讨论】:
-
为什么不使用
std::string并在需要C 版本的字符串时调用它的.c_str()方法。这样你就没有任何 malloc / 副本要处理。使用=复制strings。 -
@Golgauth:如果异常对象采用字符串对象,则需要调用 std::string:s 复制构造函数,这可能会引发异常并...停止!如果它改为引用一个字符串(相当于只存储 char 指针),问题是字符串将在异常被捕获之前死亡。所以它并没有解决问题。
-
I've answered a similar question. 没问题,它会将
filename复制到异常对象中。 -
@M M. 当要创建要抛出的对象时会出现问题。如果不在堆(或其他地方)为文件名分配空间,我就无法创建它。
标签: c++ string exception memory-management