9

在此“错误和异常处理 Boost 网页中的“我应该如何设计我的异常类? ”段落中,内容如下:

[...] 3.不要嵌入 std::string 对象或复制构造函数可能引发异常的任何其他数据成员或基类。

我必须定义一个异常类来表示文件访问时某种形式的运行时错误,所以我想从 派生它std::runtime_error,并添加一个FileName()属性来访问发生错误的文件名。

为简单起见,我的意图是添加一个std::wstring数据成员来存储文件名(以 Unicode 格式),但上述建议阻止了我。那么,我应该使用一个简单的wchar_t缓冲区作为数据成员吗?

现代桌面系统(这是我这个项目的目标平台)上,关注文件名的动态字符串分配真的很重要吗?这种分配失败的可能性有多大?我可以理解 Boost 对嵌入式系统等资源有限系统的建议,但它也适用于现代台式电脑吗?

//
// Original design, using std::wstring.
//
class FileIOError : public std::runtime_error
{
public:
    FileIOError(HRESULT errorCode, const std::wstring& filename, const char* message)
        : std::runtime_error(message),
          m_errorCode(errorCode),
          m_filename(filename)
    {
    }

    HRESULT ErrorCode() const
    {
        return m_errorCode;
    } 

    const std::wstring& FileName() const
    {
        return m_filename;
    }

private:
    HRESULT m_errorCode; 
    std::wstring m_filename;
};



//
// Using raw wchar_t buffer, following Boost's guidelines.
//
class FileIOError : public std::runtime_error
{
public:
    FileIOError(HRESULT errorCode, const wchar_t* filename, const char* message)
        : std::runtime_error(message),
          m_errorCode(errorCode)
    {
        // Safe string copy
        // EDIT: use wcsncpy_s() with _TRUNCATE, as per Hans Passant's suggestion.
        wcsncpy_s(m_filename, filename, _TRUNCATE);
    }

    HRESULT ErrorCode() const
    {
        return m_errorCode;
    } 

    const wchar_t* FileName() const
    {
        return m_filename;
    }

private:
    HRESULT m_errorCode; 
    wchar_t m_filename[MAX_PATH]; // circa 260 wchar_t's
};
4

2 回答 2

9

这种分配失败的可能性有多大?

相当低。

通常出于代码正确性的目的,您只真正关心这种可能性是零还是非零。即使在一个内建::operator new不会因为过度提交而失败的系统上,考虑你的代码将被用于替换::operator new. 或者,操作系统可能会在外部限制进程允许分配的内存量,ulimit -v或者以其他方式。

接下来考虑它失败的后果。terminate()叫做。也许你可以忍受,特别是因为它不太可能真正发生。

基本上,您是否希望您的程序在无法分配内存的情况下甚至尝试以合理的错误消息干净地退出?如果是这样,请编写额外的代码并接受错误消息长度的限制。因为 Boost 是通用库代码,所以它不会代表其用户假设他们不想尝试。

于 2012-11-17T12:43:24.457 回答
0

如果您使用的是 C++11,则可以使用移动语义和移动 std::wstring 的构造函数,即 noexcept。

于 2012-11-17T14:09:32.037 回答