标签: exception-safety

RAII的Objective-C模式?

我发现自己编写这样的代码来实现异常安全的代码:

Container* container = [Container new];
@try {
    while(someCondition) {
        ElementType* value = [someObject createObjectFromStorage];
        [container add:value]; // container retains object
        [value release];
    }

    [_container release];
    _container = [container retain];
} @finally {
    [container release];
}
Run Code Online (Sandbox Code Playgroud)

在Objective-C中还有其他一些更简洁的模式吗?

raii objective-c exception-safety

4
推荐指数
1
解决办法
1680
查看次数

std :: bad_alloc之后的std :: vector状态

我正在尝试找到一个在线参考,以查看几个标准容器的异常安全性.

在这种情况下 std::vector,它是否保持push_back调用之前的状态?我认为向量的所有对象仍然有效(没有调用析构函数).std::vectorpush_back抛出std::bad_alloc异常后提供什么保证?

c++ vector std exception-safety

4
推荐指数
1
解决办法
429
查看次数

这个来自 Effective Modern C++ 的项目仍然是最新的吗?

有效的现代 C++ 第 146 页:

void processWidget(std::shared_ptr<Widget> spw, int priority);
void cusDel(Widget *ptr);//a custom deleter
Run Code Online (Sandbox Code Playgroud)

这是 C++17 之前的不安全调用:

processWidget(std::shared_ptr<Wdiget>(new Widget, cusDel), computePriority());
Run Code Online (Sandbox Code Playgroud)

它曾经是不安全的,因为computePriority 可以new Widgetstd::share_ptr构造函数之后但之前调用,如果computePriority产生异常,动态allcoated Widget 将被泄漏。因此你可以这样做:

std::shared_ptr<Widget> spw(new Widget, cusDel);
processWidget(spw, computePriority());
Run Code Online (Sandbox Code Playgroud)

现在这将在 shared_ptr 上添加一个复制构造函数操作。所以你也可以这样做:

std::shared_ptr<Widget> spw(new Widget, cusDel);
processWidget(std::move(spw), computePriority());
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,以下代码是否仍然能够在 C++17 中泄漏内存?

processWidget(std::shared_ptr<Wdiget>(new Widget, cusDel), computePriority());
Run Code Online (Sandbox Code Playgroud)

我读过这个这个,但我仍然不能确定,相信std::shared_ptr<Wdiget>(new Widget, cusDel)computePriority()被调用processWidget前两者测序,但是我觉得computePriority()还是可以抛出后异常new之前shared_ptr采取新创建的对象的所有权。

c++ undefined-behavior exception-safety c++17

4
推荐指数
1
解决办法
157
查看次数

论函数调用中的异常安全性

f()异常安全的调用吗?

inline std::auto_ptr<C> auto_new() {
   return std::auto_ptr<C>(new C());
}

void f(std::auto_ptr<C> p1,
       std::auto_ptr<C> p2);

// ...
{
    f(auto_new(), auto_new());
}
Run Code Online (Sandbox Code Playgroud)

换句话说,auto_new()如果两个函数是内联的,那么当涉及到第一个和第二个函数调用的原子性时,它会有什么不同吗?

c++ function-call exception-safety

3
推荐指数
1
解决办法
193
查看次数

C ++ unordered_map异常安全

我在C ++规范(cplusplus.com)上徘徊,发现没有任何关于std :: unordered_map异常安全的信息

所以基本上如果我写

map["foo"]=5;
Run Code Online (Sandbox Code Playgroud)

并且由于内存或bad_alloc不足而引发异常,我可以假设我的地图是什么?

  • 它处于有效状态吗?(基本保证)
  • 它保持不变吗?(有保证)
  • 它处于无效状态吗?(不保证)

unordered-map exception-safety c++11

2
推荐指数
1
解决办法
618
查看次数

我应该在析构函数中写下文件的结尾吗?

我有一些看起来有点像这样的代码:

void writeToStream( std::ostream & outputStream )
{
    MyXmlWriter xmlWriter{ outputStream };
    xmlWriter.addNode();
    xmlWriter.addNode();
    xmlWriter.close(); // should this be called in `MyXmlWriter` destructor?
}
Run Code Online (Sandbox Code Playgroud)

close函数会写一些xml关闭标记,以便正确解析文件.构造函数编写xml文件的标头.人们可以考虑xmlWriter.close();清理代码.C++的常见建议是将清理代码放入析构函数中.这样你就永远不会忘记清理干净.但是,在我们的例子中,清理代码可能会抛出.(想象一下,file可能启用了异常,对文件的写入可能会失败.)因此,如果close()在析构函数中调用该函数,那么它应该包装在try-catch块中,该块会占用抛出的所有异常:

MyXmlWriter::~MyXmlWriter() 
{
    try
    {
        close();
    }
    catch (...)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,在这种情况下,呼叫者不会收到有关任何错误的通知.该函数writeToStream()可能无法将关闭的xml标记写入文件,而调用者不知道它.在这种情况下,最佳做法是什么?

c++ file-io destructor exception-safety

2
推荐指数
1
解决办法
1083
查看次数

make_unique的例外情况:为什么f(new T)异常是安全的

我一直在阅读GOTW102,并且想知道为什么make_unique比其他情况更安全,或者为什么f(new T(...))比例更安全f(new T1(...), new T2(...)).

make_unique博客的实施内容如下:

template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
    return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}
Run Code Online (Sandbox Code Playgroud)

现在我想知道是否f(new T(...))一般异常安全(无泄漏),或者如果它只是异常安全的情况下,make_unique因为增加的知识,建设者std::unique_ptr不扔?(T根据我的理解,如果新建的话会被泄露.

c++ exception exception-safety c++14

2
推荐指数
1
解决办法
1119
查看次数

新操作员的异常安全

这是libstdc++ 中 new 运算符的实现

_GLIBCXX_WEAK_DEFINITION void *
operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
{
  void *p;

  /* malloc (0) is unpredictable; avoid it.  */
  if (__builtin_expect (sz == 0, false))
    sz = 1;

  while ((p = malloc (sz)) == 0)
    {
      new_handler handler = std::get_new_handler ();
      if (! handler)
        _GLIBCXX_THROW_OR_ABORT(bad_alloc());
      handler ();
    }

  return p;
}
Run Code Online (Sandbox Code Playgroud)

谁保证构造函数中的异常会释放分配的内存?

更新:感谢评论员 - 实际上我的意思是新表达式的异常安全。

c++ exception-safety

2
推荐指数
1
解决办法
81
查看次数

InitOnceExecuteOnce异常安全

我在InitOnceExecuteOnce WinAPI函数上有一个异常安全问题.每当从回调函数抛出异常时,就会发生死锁.回调返回boolean标志告诉调用者数据是否成功初始化,但是如果我返回false,我将无法重新抛出异常,这不好.我尝试过这样解决问题.

try
{
    InitOnceExecuteOnce(&flag, init_once_handler, &arguments, 0);
} catch (...)
{
    InitOnceInitialize(&flag);
    throw;
}
Run Code Online (Sandbox Code Playgroud)

每当我从函数中捕获异常时,我再次初始化结构并重新抛出异常,因此其他线程将发现数据未初始化,因为标志处于初始状态.但是,它有时也会死锁,可能是因为其他线程在第一个捕获异常并再次初始化标志之前开始等待同步对象.这个问题有什么解决方案吗?

提前致谢.

c++ winapi initialization exception-safety

1
推荐指数
1
解决办法
782
查看次数

将对象移入std :: vector时的异常保证

如果在将对象移至std :: vector时内存分配失败,并且抛出bad_alloc,std :: vector是否保证从对象移出的对象不变/仍然有效?

例如:

std::string str = "Hello, World!";
std::vector<std::string> vec;

vec.emplace_back(std::move(str));
/* Is str still valid and unaltered if the previous line throws? */
Run Code Online (Sandbox Code Playgroud)

c++ stdvector exception-safety

1
推荐指数
1
解决办法
87
查看次数