在现代PC上避免使用C++异常类中的std :: wstring数据成员是否有意义?

Mr.*_*C64 9 c++ string boost memory-management exception

在" 如何设计我的异常类? "一节中的" 错误和异常处理 " 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
};
Run Code Online (Sandbox Code Playgroud)

Ste*_*sop 9

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

很低.

通常出于代码正确性的目的,您只关心该可能性是零还是非零.即使在::operator new由于过度提交而导致内置永不失败的系统上,也要考虑代码在替换的程序中使用的可能性::operator new.或者,操作系统可以通过外部ulimit -v或其他方式从外部限制允许进程分配的内存量.

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

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