自学内容网 自学内容网

关于利用C/C++ 利用编译器RAII机制,在多种编译器及跨平台下得兼容性问题。

在C/C++ 之中,我们常常利用RAII机制,来处理某个临时块得初始、及利用编译器自动析构,但这可能存在一定的致命性风险,如果你没有遇到,只是你没有过多的进行了解,挨得毒打太小,导致的。

举几个小例子:

以利用  std::lock_guard<std::mutex> 为例;

定义:

                typedef std::mutex                                          SynchronizedObject;
                typedef std::lock_guard<SynchronizedObject>                 SynchronizedObjectScope;

例一:

            bool IForwarding::TryRemove(boost::asio::ip::tcp::socket* socket, bool disposing) noexcept {
                std::shared_ptr<boost::asio::ip::tcp::socket> ptr;
                IForwarding::SynchronizedObjectScope scope(syncobj_);
                return Dictionary::TryRemove(sockets_, socket, ptr);
            }

上述例子,在不同得编译器根平台上面会存在不同得效果,取决于编译器得实现,按照人们显示理解:

在 Dictionary::TryRemove 函数执行完毕以后,其键值通过FAR指针反弹到调用方PTR变量之中。

在调用方 TryRemove 函数执行结束后,先执行 SynchronizedObjectScope 的析构,

在执行 std::shared_ptr 的析构函数,在很多编译器之中是这样,但在一些编译器之中,

它可能不是这样执行的,这就带来了一些不可控制的因素,所以看上去,我们需要例二:

            bool IForwarding::TryRemove(boost::asio::ip::tcp::socket* socket, bool disposing) noexcept {
                std::shared_ptr<boost::asio::ip::tcp::socket> ptr; {
                    IForwarding::SynchronizedObjectScope scope(syncobj_);
                    return Dictionary::TryRemove(sockets_, socket, ptr);
                }
            }

其实这种在所有的编译器当中,都是可以正确执行的,看上去已经完全没有问题了,但当人们启用编译器 -O3、-OX 编译器最大优化时,它在一些编译器及平台上面仍旧会出现问题,所以,这个时候,我们需要例三:

            bool IForwarding::TryRemove(boost::asio::ip::tcp::socket* socket, bool disposing) noexcept {
                std::shared_ptr<boost::asio::ip::tcp::socket> ptr; 
                do {
                    IForwarding::SynchronizedObjectScope scope(syncobj_);
                    return Dictionary::TryRemove(sockets_, socket, ptr);
                } while (false);
            }

上述的代码,在绝大多数编译器及平台上面都可以确保流程跟我们预期的一致性,但仍旧不能保证在优化之后会像例二一般,出现问题,虽然这段代码的编写方式,比例子二在更多的编译器、及平台上面有保证,所以我们需要例子四。

例子四点一:

            bool IForwarding::TryRemove(boost::asio::ip::tcp::socket* socket, bool disposing) noexcept {
                std::shared_ptr<boost::asio::ip::tcp::socket> ptr; 
                for (;;) {
                    IForwarding::SynchronizedObjectScope scope(syncobj_);
                    return Dictionary::TryRemove(sockets_, socket, ptr);
                }
            }

例子四点二:


            bool IForwarding::TryRemove(boost::asio::ip::tcp::socket* socket, bool disposing) noexcept {
                std::shared_ptr<boost::asio::ip::tcp::socket> ptr; 
                bool result = false;
                for (;;) {
                    IForwarding::SynchronizedObjectScope scope(syncobj_);
                    result = Dictionary::TryRemove(sockets_, socket, ptr);
                    break;
                }

                return result;
            }

以上无论那种形式,都可以在所有的C/C++编译器及平台上面,按照我们预期流程正确执行,在C/C++之中编译器优化。

{ 代码 } ,do { 代码 } while (0, false); 这样的形式,都可能被优化错误,因为在开编译器O3/OX优化时,它们会被编译器预处理,进行栅格退化,退化的结果是不可控制的。

在C/C++ 之中,for (;;) 、while (1) ;;; 是不会被退化的,因为编译器没有这样的优化策略,当然,如果你通过禁用编译器优化的目的,也可以解决问题,只不过这可能不符合,我们的能效预期。


原文地址:https://blog.csdn.net/liulilittle/article/details/140289076

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!