簡體   English   中英

std :: exception使用來自本地對象的消息

[英]std::exception using message from local object

以下代碼是否安全地使用自定義消息拋出異常?

#include <exception>
#include <sstream>
#include <string>
#include <iostream>

int main() {
  try {
    std::ostringstream msg;
    msg << "give me " << 5;
    throw std::exception(msg.str().c_str());
  } catch (std::exception& e) {
    std::cout << "exception: " << e.what();
  }
}

使用VC ++ - 2008,這給出了:

exception: give me 5

但現在我想知道為什么來自本地對象msg的消息“給我5”仍然可以在catch塊中找到? 在打印消息時,應該刪除流和臨時字符串對象嗎? 順便說一句:這種為異常生成消息的方式似乎也適用於多個函數,如果在打印異常之前在catch塊中分配了新內存。

或者是否需要使用std :: string成員定義自定義異常類,以便安全地保留消息直到打印它。

這是非常安全的。 將C字符串作為單個參數的構造函數構成字符串的副本。 采用C字符串和長度參數的構造函數允許您指定不分配內存並存儲指向字符串的指針(忽略length參數)。

請注意,這兩個構造函數是std::exception類的擴展,並不是標准的。 另請注意,將C字符串作為單個參數的構造函數未標記為顯式。

沒關系。

根據§15.1/ 3:

拋出異常copy-initializes(8.5,12.8)一個臨時對象,稱為異常對象。

和§15.1/ 4:

除非在3.7.4.1中指出,否則異常對象的內存以未指定的方式分配。 如果處理程序通過重新拋出退出,則控制將傳遞給另一個處理程序以獲取相同的異常。 異常對象在異常的最后一個活動處理程序退出之后通過除了重新拋出之外的任何方式退出...

所以throw expression

表達式將被復制(新對象將由復制構造函數創建),您不必擔心本地對象。

關於你擔心的msgconst char* ......這是微軟的實現:

exception::exception(const char * const & _What)
: _Mywhat(NULL), _Mydofree(false)
{
   _Copy_str(_What);
 //^^^^^^^^^^^^^^^^^
}

void exception::_Copy_str(const char * _What)
{
   if (_What != NULL)
   {
      const size_t _Buf_size = strlen(_What) + 1;
      _Mywhat = static_cast<char *>(malloc(_Buf_size));
       if (_Mywhat != NULL)
       {
         _CRT_SECURE_STRCPY(const_cast<char *>(_Mywhat), _Buf_size, _What);
       //^^^^^^^^^^^^^^^^^^
         _Mydofree = true;
       }
   }
 }

它復制_What不只是存儲指針。

不,這不安全,因為std::exception沒有構造函數在標准中使用char *。 您正在使用MS擴展程序。 為了使其可移植和安全,請使用std::runtime_error ,您可以在ctor中傳遞std::string

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM