我想做点什么
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&amp; 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
}
答案 0 :(得分:1)
你只需要面对这样一个事实:创建一个包含任意大小字符串的异常必须分配内存,这可能会失败。你唯一能做的就是缓解。
首先,可能发生的最糟糕的事情是throw子表达式成功,但是将异常复制到异常存储器会抛出。在这种情况下,std :: terminate立即被调用,你被搞砸了。你不希望这样。
在实践中,这很少是一个问题,因为这个副本通常会被删除,这意味着没有机会抛出。此外,如果您使用的是C ++ 11,请确保您的异常具有无抛出移动构造函数。它将优先于复制构造函数使用,因此您不会冒异常的风险。
其次,throw子表达式本身可能会抛出。如果是这样,那么将抛出新的异常而不是您想要的异常。在您的情况下,如果您在异常类中有一个std :: string成员,那么您很可能会得到一个std :: bad_alloc异常而不是您想要抛出的ExceptionWinapiFile。你要问自己的问题是,这真的是一个问题吗?如果你的内存太低而无法为文件名分配足够的空间,你真的还在乎文件没有被打开吗?有可能因为内存不足而失败,如果它没有失败,无论你怎么处理文件都可能因内存不足而失败。
除非你有非常非常具体的要求,否则我说不要担心。把std :: string成员放在那里,你会没事的。