首页 \ 问答 \ 复杂的错误处理(Complex error handling)

复杂的错误处理(Complex error handling)

我有一个特别令人讨厌的网络代码。 我正在使用asio,但这对于这个问题并不重要。 我假设除了关闭套接字之外没有办法取消绑定套接字。 问题是open()bind()listen()都可以抛出system_error 。 所以我用一个简单的try/catch处理代码。 代码写得很破碎。

using namespace boost::asio;

class Thing
{
public:

   ip::tcp::endpoint m_address;

   ip::tcp::acceptor m_acceptor;

   /// connect should handle all of its exceptions internally.
   bool connect()
   {
      try
      {
         m_acceptor.open( m_address.protocol() );
         m_acceptor.set_option( tcp::acceptor::reuse_address(true) );

         m_acceptor.bind( m_address );
         m_acceptor.listen();

         m_acceptor.async_accept( /*stuff*/ );
      }
      catch( const boost::system::system_error& error )
      {
         assert(acceptor.is_open());
         m_acceptor.close();
         return false;
      }
      return true;
   }

   /// don't call disconnect unless connect previously succeeded.
   void disconnect()
   {
      // other stuff needed to disconnect is ommited
      m_acceptor.close();
   }
};

错误是如果套接字连接失败,它将尝试在catch块中关闭它,并抛出另一个关于关闭从未打开的接受器的system_error。

一种解决方案是在catch块中添加一个if( acceptor.is_open() ) ,但这种方法错了。 有点像将C风格的错误检查与c++异常混合在一起。 如果我去那条路线,我也可以使用open()的非投掷版本。

boost::system::error_code error;
acceptor.open( address.protocol, error );
if( ! error )
{
    try
    {
       acceptor.set_option( tcp::acceptor::reuse_address(true) );

       acceptor.bind( address );
       acceptor.listen();

       acceptor.async_accept( /*stuff*/ );
    }
    catch( const boost::system::system_error& error )
    {
       assert(acceptor.is_open());
       acceptor.close();
       return false;
    }
}
return !error;

有没有一种优雅的方法来使用RAII和try/catch块来处理这些可能的异常?

在尝试避免使用异常时if( error condition )样式错误处理时,我是错误的吗?


I've got a particularly ornery piece of network code. I'm using asio but that really doesn't matter for this question. I assume there is no way to unbind a socket other than closing it. The problem is that open(), bind(), and listen() can all throw a system_error. So I handled the code with a simple try/catch. The code as written in broken.

using namespace boost::asio;

class Thing
{
public:

   ip::tcp::endpoint m_address;

   ip::tcp::acceptor m_acceptor;

   /// connect should handle all of its exceptions internally.
   bool connect()
   {
      try
      {
         m_acceptor.open( m_address.protocol() );
         m_acceptor.set_option( tcp::acceptor::reuse_address(true) );

         m_acceptor.bind( m_address );
         m_acceptor.listen();

         m_acceptor.async_accept( /*stuff*/ );
      }
      catch( const boost::system::system_error& error )
      {
         assert(acceptor.is_open());
         m_acceptor.close();
         return false;
      }
      return true;
   }

   /// don't call disconnect unless connect previously succeeded.
   void disconnect()
   {
      // other stuff needed to disconnect is ommited
      m_acceptor.close();
   }
};

The error is if the socket fails to connect it will try to close it in the catch block and throw another system_error about closing an acceptor that has never been opened.

One solution is to add an if( acceptor.is_open() ) in the catch block but that tastes wrong. Kinda like mixing C-style error checking with c++ exceptions. If I where to go that route, I may as well use the non-throwing version of open().

boost::system::error_code error;
acceptor.open( address.protocol, error );
if( ! error )
{
    try
    {
       acceptor.set_option( tcp::acceptor::reuse_address(true) );

       acceptor.bind( address );
       acceptor.listen();

       acceptor.async_accept( /*stuff*/ );
    }
    catch( const boost::system::system_error& error )
    {
       assert(acceptor.is_open());
       acceptor.close();
       return false;
    }
}
return !error;

Is there an elegant way to handle these possible exceptions using RAII and try/catch blocks?

Am I just wrong headed in trying to avoid if( error condition ) style error handling when using exceptions?


原文:https://stackoverflow.com/questions/2730963
更新时间:2023-11-15 20:11

最满意答案

此代码适用于您的方案。 但是如果你需要一个泛型函数,它适用于多个嵌套数组,我们需要编写一个递归函数。

<?php
$json_contents = file_get_contents('test.json'); //Placed your json in test.json 

$output = array();
$json_array = json_decode($json_contents, true); //Convert json to php array 

foreach ($json_array as $element){  
    foreach ($element as $attribute => $value){ //parse through each attribute 
      if(is_array($value)){   //if value is an array, parse through it and update output array accordingly
          foreach ($value as $a => $v) {
            $output[$attribute.'_'.$a] = $v;
          }
      }
      else{      //if value is not an array, get those elements as they are into $output 
          $output[$attribute] = $value;
      }
  }
}
print_r($output);  //You can convert $output into json using json_encode($output);
print_r($json_array);

test.json:

{
  "company": {
    "name": "Example Co",
    "legalName": "Example Co LLC",
    "domain": "example.com",
    "domainAliases": [
      "example01.com",
      "example02.com",
      "example03.com"
    ],
    "category": {
      "sector": "Financials",
      "industryGroup": "Diversified Financial Services",
      "industry": "Diversified Financial Services",
      "subIndustry": "Financial Services"
    },
    "tags": [
      "Marketplace",
      "B2C",
      "Financial Services"
    ],
    "foundedYear": null,
    "tech": [
      "google_analytics",
      "hotjar",
      "outlook"
    ]
  }
}

输出:

Array
(
    [name] => Example Co
    [legalName] => Example Co LLC
    [domain] => example.com
    [domainAliases_0] => example01.com
    [domainAliases_1] => example02.com
    [domainAliases_2] => example03.com
    [category_sector] => Financials
    [category_industryGroup] => Diversified Financial Services
    [category_industry] => Diversified Financial Services
    [category_subIndustry] => Financial Services
    [tags_0] => Marketplace
    [tags_1] => B2C
    [tags_2] => Financial Services
    [foundedYear] => 
    [tech_0] => google_analytics
    [tech_1] => hotjar
    [tech_2] => outlook
)

This code works good for your scenario. But if you need a generic function, that works with multiple nested arrays, we need to write a recursive function.

<?php
$json_contents = file_get_contents('test.json'); //Placed your json in test.json 

$output = array();
$json_array = json_decode($json_contents, true); //Convert json to php array 

foreach ($json_array as $element){  
    foreach ($element as $attribute => $value){ //parse through each attribute 
      if(is_array($value)){   //if value is an array, parse through it and update output array accordingly
          foreach ($value as $a => $v) {
            $output[$attribute.'_'.$a] = $v;
          }
      }
      else{      //if value is not an array, get those elements as they are into $output 
          $output[$attribute] = $value;
      }
  }
}
print_r($output);  //You can convert $output into json using json_encode($output);
print_r($json_array);

test.json :

{
  "company": {
    "name": "Example Co",
    "legalName": "Example Co LLC",
    "domain": "example.com",
    "domainAliases": [
      "example01.com",
      "example02.com",
      "example03.com"
    ],
    "category": {
      "sector": "Financials",
      "industryGroup": "Diversified Financial Services",
      "industry": "Diversified Financial Services",
      "subIndustry": "Financial Services"
    },
    "tags": [
      "Marketplace",
      "B2C",
      "Financial Services"
    ],
    "foundedYear": null,
    "tech": [
      "google_analytics",
      "hotjar",
      "outlook"
    ]
  }
}

Output:

Array
(
    [name] => Example Co
    [legalName] => Example Co LLC
    [domain] => example.com
    [domainAliases_0] => example01.com
    [domainAliases_1] => example02.com
    [domainAliases_2] => example03.com
    [category_sector] => Financials
    [category_industryGroup] => Diversified Financial Services
    [category_industry] => Diversified Financial Services
    [category_subIndustry] => Financial Services
    [tags_0] => Marketplace
    [tags_1] => B2C
    [tags_2] => Financial Services
    [foundedYear] => 
    [tech_0] => google_analytics
    [tech_1] => hotjar
    [tech_2] => outlook
)

相关问答

更多

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。