C/C++ 通过C语言可变参数打印(正常参数、正常格式化,运行不确定时间后崩溃)

在 C/C++ 之中,有时会遇到一些疑难杂症,但大多数情况下不会触发它,但如果触发它导致崩溃,的确会让人心态很炸裂。

我们知道我们想要提供C语言接口的动态参数传递给其它C动态参数函数,会通过va_list 来转发调用,这个在C语言之中是不存在问题的,但是在 C++ 之中它可能存在一些问题,这是因为 C++ 语言之中函数的调用协议之间是不确定的。

它可能是__fastcall、__thiscall、__stdcall 这些,而C语言函数调用协议是 __cdecl,这就带来潜在的不确定风险性。

即这段代码从语义执行上似乎都没有出现过任何问题,但是运行一段时间之后就导致崩溃,同时在C语言可变参数之中使用 STL容器(如 std::string)也会导致莫名其妙的崩溃,但在绝大多数时间内它都被正确执行。

解决这类问题在 C/C++ 语言之中,我们应当首选通过 C/C++ 动态参数模板来实现,例如:我们期望对于 snprintf 的动态参数转发,并且返回std::string字符串,正确做法与不正确做法。

正确:(一半,开O3后有一定崩溃风险,看脸运行时间多长)

    std::string test(const char* format, ...) noexcept {char buffer[8096];va_list ap;va_start(ap, format);vsnprintf(buffer, sizeof(buffer), format, args);va_end(ap);return buffer;}

正确:

    template <class... A>std::string                                     test(const char* format, A&&... args) noexcept {char buffer[8096];snprintf(buffer, sizeof(buffer), format, std::forward<A&&>(args)...);return buffer;}

错误:

    auto printfn = [](const char* format, ...) noexcept{va_list ap;va_start(ap, format);std::string st = test(format, ap);va_end(ap);};

即自己在 C/C++ 中声明了:
std::string test(const char* format, va_list args) noexcept;

调用 vsnprintf 函数传递C语言可变参数列表。

在封装C语言可变参数 ...(语法)方式在封装传递,100%会遭遇较为快速的程序崩溃,但也不是立马崩溃,一般性调试期间基本不会崩。

但也不意味着完全不崩,只是要等它重复次数足够多,就是需要一定时间,这并非内存损坏问题。

在 C/C++ 语言之中,必须通过可变参数模板方式来传递可变参数列表,否则都是不安全,存在不缺行崩溃风险的。

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

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

相关文章

解决方案|珈和科技推出农业特色产业数字化服务平台

今年中央一号文件提出&#xff0c;鼓励各地因地制宜大力发展特色产业&#xff0c;支持打造乡土特色品牌。 然而&#xff0c;农业特色产业的生产、加工和销售仍然面临诸多挑战。产品优质不能优价&#xff0c;优质不能优用的现象屡见不鲜&#xff0c;产业化程度低、生产附加值不…

Linux进程概念僵尸进程孤儿进程

文章目录 一、什么是进程二、进程的状态三、Linux是如何做的&#xff1f;3.1 R状态3.2 S状态3.3 D状态3.4 T状态3.5 t状态3.6 X状态3.7 Z状态 四、僵尸进程4.1 僵尸进程危害 五、孤儿进程 一、什么是进程 对于进程理解来说&#xff0c;在Windows上是也可以观察到的&#xff0c…

蓝桥杯(3.10)

1219. 移动距离 import java.util.Scanner; public class Main{public static void main(String[] args) {Scanner sc new Scanner(System.in);int w sc.nextInt();int m sc.nextInt();int n sc.nextInt();m--;n--;//由从1开始变为从0开始//求行号int x1 m/w, x2 n/w;//…

数据结构与算法第三套试卷小题

1.删除链表节点 **分析&#xff1a;**首先用指针变量q指向结点A的后继结点B&#xff0c;然后将结点B的值复制到结点A中&#xff0c;最后删除结点B。 2.时间复杂度的计算 **分析&#xff1a;**当涉及嵌套循环的时候&#xff0c;我们可以直接分析内层循环即可&#xff0c;看内…

2024年春招,如何做一份高水平的简历?(附个人简历模板)

抓对这几个重点,你想不通过简历面都难! HR想看到什么?雇主想看到什么?你未来的Leader想看到什么? 1. 简历模板:第一印象至关重要 专业与个性并存:选择一个既专业又有个性的模板。例如,如果你是一名工程师,可以选择一个简洁、有技术感的模板;如果是艺术行业,可以选…

Docker 的资源控制

目录 Docker 的资源控制为什么需要资源控制&#xff1f;控制内存使用限制 CPU 使用磁盘 I/O 控制网络带宽限制实践建议 Docker 资源控制&#xff1a;保障性能与稳定性Docker资源控制概览内存限制CPU限制磁盘 I/O 控制网络带宽管理实际应用 Docker 启动后的 更新资源管理 Docker…

面试官:线程调用2次start会怎样?我支支吾吾没答上来

写在开头 在写完上一篇文章《Java面试必考题之线程的生命周期&#xff0c;结合源码&#xff0c;透彻讲解!》后&#xff0c;本以为这个小知识点就总结完了。 但刚刚吃晚饭时&#xff0c;突然想到了多年前自己面试时的亲身经历&#xff0c;决定再回来补充一个小知识点&#xff…

Dgraph 入门教程三《linux本地部署》

上一章中&#xff0c;我们用的官方的Clound操作的&#xff0c;怎么在本地部署一套Dgraph呢。这一章将做详细介绍。安装有好几种方式&#xff0c;最简单的就是联网部署。因为项目需要&#xff0c;这里先不介绍和测试线上部署了&#xff0c;只介绍离线部署。 1、下载安装包 Rel…

理论学习:nn.CrossEntropyLoss

该标准计算输入 logits 和目标之间的交叉熵损失。 代码实战 该损失函数结合了nn.LogSoftmax()和nn.NLLLoss()两个函数。它在做分类&#xff08;具体几类&#xff09;训练的时候是非常有用的。在训练过程中&#xff0c;对于每个类分配权值&#xff0c;可选的参数权值应该是一个…

cdn和oss有什么区别

CDN&#xff08;内容分发网络&#xff09;和OSS&#xff08;对象存储服务&#xff09;是两种常见的互联网技术&#xff0c;它们在内容存储和分发方面有着不同的功能和特点。 CDN&#xff1a;加速网络内容分发 CDN通过部署在全球各地的节点服务器&#xff0c;将静态内容缓存到离…

langchain入门

1、langchain的2个能力 可以将 LLM 模型与外部数据源进行连接允许与 LLM 模型进行交互 2、基础功能 LLM 调用 支持多种模型接口&#xff0c;比如 OpenAI、Hugging Face、AzureOpenAI ...Fake LLM&#xff0c;用于测试缓存的支持&#xff0c;比如 in-mem&#xff08;内存&am…

开源是什么?——跟老吕学Python编程

开源是什么&#xff1f;——跟老吕学Python编程 开源是什么&#xff1f;开放源代码软件是什么&#xff1f;开源软件许可证是什么&#xff1f;开放源代码软件是什么&#xff1f;开放源代码的软件代表有什么&#xff1f;开放源代码软件与自由软件的概念 开源的定义是什么&#xf…

JavaScript基础6之执行上下文、作用域链、函数创建、函数激活、checkScope的执行过程、闭包、this

JavaScript基础 执行上下文执行上下文中的属性变量对象全局上下文的变量对象函数上下文执行过程进入执行上下文代码执行思考题 作用域链函数创建函数激活checkScope的执行过程总结 闭包分析闭包 this 执行上下文 执行上下文中的属性 每一个执行上下文都有三个核心属性 变量对…

职场逆袭!如何打造‘黄金简历’

现在的职场&#xff0c;无论是哪个行业都特别卷&#xff0c;想要找到一份满意&#xff0c;不仅要求你要拥有丰富的工作经验&#xff0c;而且还要求你的简历足够精彩&#xff0c;这样才能在一众求职者中脱颖而出&#xff01; 一、希赛老师在线指导 之前&#xff0c;小赛分享了…

c#WPF绑定

在 C# WPF 中&#xff0c;绑定是一种将 UI 元素&#xff08;如文本框、列表框等&#xff09;与数据源&#xff08;如对象、集合等&#xff09;关联起来的技术。通过绑定&#xff0c;可以在 UI 元素上显示和更新数据源中的数据&#xff0c;实现数据的双向同步。 下面是一个简单的…

CTP-API开发系列之四:接口对接准备

CTP-API开发系列之四&#xff1a;接口对接准备 CTP-API开发系列之四&#xff1a;接口对接准备CTP-API文件清单CTP-API通用规则命名规则Spi与Api CTP-API通讯模式开发语言选择 CTP-API开发系列之四&#xff1a;接口对接准备 CTP-API文件清单 文件名说明ThostFtdcTraderApi.h交…

mysql安装目录

方法一 输入如下sql命令 SELECT datadir;方法二 点击

docker-swarm集群管理命令

为什么选择swarm集群&#xff1f; 灵魂疑问&#xff1a;同样是集群&#xff0c;为什么选择docker swarm&#xff0c;而不不选择k8s或者k3s&#xff1f; 我的需求场景&#xff1a;不想直接用docker或者java -jar直接跑&#xff0c;修改前是使用java -jar方式&#xff0c;这两种…

Redis冲冲冲——Redis持久化方式及其区别

目录 引出Redis持久化方式Redis入门1.Redis是什么&#xff1f;2.Redis里面存Java对象 Redis进阶1.雪崩/ 击穿 / 穿透2.Redis高可用-主从哨兵3.持久化RDB和AOF4.Redis未授权访问漏洞5.Redis里面安装BloomFilte Redis的应用1.验证码2.Redis高并发抢购3.缓存预热用户注册验证码4.R…

代码背后的女性:突破性别壁垒的技术先驱

个人主页&#xff1a;17_Kevin-CSDN博客 收录专栏&#xff1a;《程序人生》 引言 在计算机科学的历史长河中&#xff0c;有许多杰出的女性为这个领域的发展做出了重要贡献。她们不仅在技术上取得了卓越成就&#xff0c;还打破了性别壁垒&#xff0c;为后来的女性树立了榜样。今…