关于利用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) ;;; 是不会被退化的,因为编译器没有这样的优化策略,当然,如果你通过禁用编译器优化的目的,也可以解决问题,只不过这可能不符合,我们的能效预期。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/869436.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

08.C2W3.Auto-complete and Language Models

往期文章请点这里 目录 N-Grams: OverviewN-grams and ProbabilitiesN-gramsSequence notationUnigram probabilityBigram probabilityTrigram ProbabilityN -gram probabilityQuiz Sequence ProbabilitiesProbability of a sequenceSequence probability shortcomingsApproxi…

基数排序算法Python实现

1. 基数排序原理和步骤 基数排序是一种非比较型的排序算法&#xff0c;特别适用于处理整数或者字符串等可以分解为多个部分的数据。其基本思想是按位&#xff08;或字符&#xff09;进行排序&#xff0c;从最低有效位到最高有效位逐次排序。基数排序常分为LSD&#xff08;Leas…

字节码编程javassist之生成带有注解的类

写在前面 本文看下如何使用javassist生成带有注解的类。 1&#xff1a;程序 测试类 package com.dahuyou.javassist.huohuo.cc;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import ja…

MyBatisPlus实现增删改查

文章目录 MyBatisPlus实现增删改查基本操作分页查询配置分页插件 MyBatisPlus实现增删改查 实体类GkUser package com.geekmice.springbootselfexercise.entity;import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField;…

保姆级教程:Linux (Ubuntu) 部署流光卡片开源 API

流光卡片 API 开源地址 Github&#xff1a;https://github.com/ygh3279799773/streamer-card 流光卡片 API 开源地址 Gitee&#xff1a;https://gitee.com/y-gh/streamer-card 流光卡片在线使用地址&#xff1a;https://fireflycard.shushiai.com/ 等等&#xff0c;你说你不…

0基础学会在亚马逊云科技AWS上搭建生成式AI云原生Serverless问答QA机器人(含代码和步骤)

小李哥今天带大家继续学习在国际主流云计算平台亚马逊云科技AWS上开发生成式AI软件应用方案。上一篇文章我们为大家介绍了&#xff0c;如何在亚马逊云科技上利用Amazon SageMaker搭建、部署和测试开源模型Llama 7B。下面我将会带大家探索如何搭建高扩展性、高可用的完全托管云原…

C++线程安全队列

在 C 中&#xff0c;多线程队列&#xff08;queue&#xff09;的实现通常需要考虑线程安全问题&#xff0c;特别是在多个线程需要同时对队列进行操作时。C 标准库中的 std::queue 并不是线程安全的&#xff0c;因此我们需要引入额外的机制来确保线程安全。常用的方法是使用互斥…

FullCalendar的使用,react日历组件

1.下载 yarn add fullcalendar/core fullcalendar/react fullcalendar/daygrid 2.运行 import React from react; import FullCalendar from "fullcalendar/react"; import dayGridPlugin from "fullcalendar/daygrid";const ExperimentalSchedule () …

2024百度之星第三场第一题 数星星

天上有 n 颗星星&#xff0c;每颗星星自第 bi​ 秒开始&#xff08;包含第 bi​ 秒&#xff09;&#xff0c;每 ai​ 秒便会闪烁一次&#xff0c;小度 今晚有一点失眠&#xff0c;所以他想来数星星&#xff0c;天上的星星每闪烁一次&#xff0c;小度便会在心中记一次数&#xf…

初识STM32:寄存器编程 × 库函数编程 × 开发环境

STM32的编程模型 假如使用C语言的方式写了一段程序&#xff0c;这段程序首先会被烧录到芯片当中&#xff08;Flash存储器中&#xff09;&#xff0c;Flash存储器中的程序会逐条的进入CPU里面去执行。 CPU相当于人的一个大脑&#xff0c;虽然能执行运算和执行指令&#xff0c;…

hutool ExcelUtil 导出导入excel

引入依赖 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.15</version></dependency>文件导入 public void savelist(String filepath,String keyname){ExcelReader reader Exce…

面试官:讲一下如何终止一个 Promise 继续执行

我们知道 Promise 一旦实例化之后&#xff0c;状态就只能由 Pending 转变为 Rejected 或者 Fulfilled&#xff0c; 本身是不可以取消已经实例化之后的 Promise 了。 但是我们可以通过一些其他的手段来实现终止 Promise 的继续执行来模拟 Promise 取消的效果。 Promise.race …

索引知识总结

一、什么是索引&#xff1f; 索引是在数据库管理中一个非常重要的概念&#xff0c;它是一种数据结构&#xff0c;设计用于提高数据库查询的效率。索引类似于书籍的目录或索引页&#xff0c;可以帮助数据库管理系统快速定位和检索数据&#xff0c;而不必检查数据库中的每一行。…

SAP_MMABAP模块_MM60物料清单新增物料组描述字段

业务背景&#xff1a; 用户需要在系统标准的物料主数据查询报表MM60中&#xff0c;添加物料组描述&#xff0c;一直以来&#xff0c;我都觉得标准的MM60显示的内容字段不够多&#xff0c;不太好用。 以往都是给用户新开发一个物料主数据查询报表来解决的&#xff0c;但是这次刚…

数学建模及国赛

认识数学建模及国赛 认识数学建模 环境类&#xff1a;预测一下明天的气温 实证类&#xff1a; 评价一下政策的优缺点 农业类&#xff1a; 预测一下小麦的产量 财经类&#xff1a; 分析一下理财产品的最优组合 规划类&#xff1a; 土地利用情况进行 合理的划分 力学类&#xf…

ProFuzzBench入门教学——使用(Ubuntu22.04)

ProFuzzBench是网络协议状态模糊测试的基准测试。它包括一套用于流行协议&#xff08;例如 TLS、SSH、SMTP、FTP、SIP&#xff09;的代表性开源网络服务器&#xff0c;以及用于自动执行实验的工具。详细参考&#xff1a;阅读笔记——《ProFuzzBench: A Benchmark for Stateful …

一句话彻底搞懂Java的编译和执行过程

编译和运行可以在不同的计算机上实现。 编译阶段&#xff1a;由Javac编译器将 .Java 的源文件编译为 .class 的字节码文件&#xff1b; 运行阶段&#xff1a; jvm中Java编译器运行 .class 的字节码文件&#xff0c;运行过程中&#xff0c;类加载器从硬盘中找到该字节码文件并…

WPF引入多个控件库使用

目的 设计开发时有的控件库的一部分符合我们想要的UI样式&#xff0c;另一部分来自另一个控件库&#xff0c;想把两种库的样式做一个整合在同一个控件资源上。单纯通过引用的方式会导致原有样式被覆盖。这里通过设置全局样式的方式来实现。 1.安装控件库nuget包&#xff1a;H…

Spring添加自定义拦截器的方法

一、添加一个自定义拦截器并实现HandlerInterceptor方法 public class CartInterceptor implements HandlerInterceptor {//ThreadLocal实质是个map&#xff0c;在同一个线程共享数据public static ThreadLocal<UserInfoTO> threadLocal new ThreadLocal<>();/* …

uniapp 防止重复提交数据

当用户快速点击按钮时候。我们可以统一在 请求拦截 中做防止重复提交数据的处理 以下是使用uview2封装的request请求 import { autoLogin, getUserInfo } from /utils/method.js import { refreshToken } from /api/login.js const serversUrl require(./serversUrl.js).ser…