新手BUG:在声明了返回值的函数中不写返回值

news2024/11/23 21:16:52


 本文对两个分别以int和string为返回值类型的函数进行分析,说明了在有返回值的函数中不写返回值会产生的问题。然后给出在编译阶段检查出这样的问题的办法。

一、背景

在软件测试环节发现,函数会在返回之前coredump。经过排查发现,在这个会产生core的函数中调用了另外一个返回值类型为string的函数。而在这个返回值为string的函数中的某些分支中没有写明确的返回语句导致返回的string是个无效数值。

二、具体现象

在使用O0和O2优化级别编译的时候出现coredump,且coredump的原因都是无效指针释放。 源代码

#include <stdio.h>
#include <string>
std::string get_string(int idx){
    if(idx <= 1)
         return std::string("<1");
}

int main() {
    get_string(2);
    return 0;
}

使用O0或者O2编译

g++ noreturn.cpp -g -O0
# g++ noreturn.cpp -g -O2

三、从汇编代码看这个问题

3.1 返回值为int的情况
3.1.1 汇编语言对照

  getint和getint_error两个函数都被声明了int类型的返回值。区别在于,getint函数中有明确返回语句 return 10, 而getint_error函数没有明确的返回语句。

3.1.2 汇编语言分析

  从汇编代码可以看出区别,当被调用函数中(getint)有return 10语句时,函数的返回值被保存在eax寄存器中返回给调用者,main函数作为函数调用者从eax寄存器获取返回值使用。

  当函数中(getint_error)没有返回语句的时候,eax寄存器将不会被赋值,这时候main函数作为调用者通过eax获取的返回值是上次函数调用(getint)的结果。

  具体执行情况为:执行第35行 auto i1 = getint(); 时,eax寄存器保存了10作为函数返回值赋值给了i1; 执行第36行 auto i2 = getint_error();时,eax寄存器并没有被getint_error函数赋值,因此仍然保存着上次函数调用的结果10。

  最终,i1和i2两个变量是相等的,都是通过getint函数获取的eax寄存器的值被赋值的。

3.1.3 gdb单步调试确认

  通过gdb单步调试,也可以确认以上分析的合理性,从最后的执行结果可以看出,i1和i2两个变量的数值是一样的。

3.2 返回值为string的情况
3.2.1 汇编语言对照

  getstr和getstr_error两个函数都被声明了std::string类型的返回值。区别在于,getstr函数中有明确返回语句 return std::string(), 而getstr_error函数没有明确的返回语句。

3.2.2 汇编语言分析

  从汇编代码可以看出区别,当被调用函数中(getstr)有return 语句时,将会调用std::string的构造函数,并将函数的返回值被保存在rax寄存器中返回给调用者,main函数作为函数调用者从rax寄存器获取返回值使用。

  当函数中(getstr_error)没有返回语句的时候,rax寄存器虽然被赋值,却被赋值为无效值,这时候main函数作为调用者通过rax获取的返回值是无效的。

  当main函数对s1,s2这两个局部变量进行析构的时候,s2先被正常析构,s1析构的时候将产生异常错误。

3.2.3 gdb单步调试确认

  通过gdb单步调试,也可以确认以上分析的合理性。按照构造和析构顺序相反的原则,s2先被正常析构(绿色框),s1析构时报错(红色框__GI___libc_free (mem=0x280) at malloc.c:3102)。

  通过gdb打印s1和s2的变量内容后可以看出问题。

   s1的内存地址为0x7fffffffdd40,其中,s1的size为 0x10000ffff, 数据地址为 0x280,因此s1的size和数据地址都是无效的,因此在析构时free报错。

(gdb) print /x ((std::string*)0x7fffffffdd40)->size()
$35 = 0x10000ffff
(gdb) print /x ((std::string*)0x7fffffffdd40)->_M_dataplus
$43 = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x280}
(gdb) print /x ((std::string*)0x7fffffffdd40)->_M_dataplus->_M_p
$44 = 0x280

   s2的内存地址为0x7fffffffdd60,其中,s2的size为 0x0, 数据地址为 0x7fffffffdd70,因此s2的size和数据地址都是有效的,因此在析构时正常。

(gdb) print /x ((std::string*)0x7fffffffdd60)->size()
$34 = 0x0
(gdb) print /x ((std::string*)0x7fffffffdd60)->_M_dataplus
$41 = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7fffffffdd70}
(gdb) print /x ((std::string*)0x7fffffffdd60)->_M_dataplus->_M_p
$42 = 0x7fffffffdd70

四、如何避免这种问题

   解决办法:在编译时 添加编译选项-Werror=return-type ,在编译时对有明确返回值但是无返回语句的函数进行报错拦截。

添加编译选项前,默认是输出一条警告:

添加编译选项后,输出一条报错:

 

关注非科班CPP程序员,一起学习,一起进步

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

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

相关文章

单个相机矫正畸变

1、通过标定助手获取到内参外参&#xff0c;外参在此无效&#xff0c;只用到了内参 2、然后通过halcon算子进行矫正 参考&#xff1a;超人视觉

【骑士放置——最大独立集】

题目 思路 最大独立集n-最小点覆盖n-最大边匹配 代码 #include <bits/stdc.h> using namespace std; #define x first #define y second typedef pair<int, int> PII; const int N 110; int dx[8] {-2, -1, 1, 2, 2, 1, -1, -2}; int dy[8] {1, 2, 2, 1, -1, …

【每日题解】3226. 使两个整数相等的位更改次数

给你两个正整数 n 和 k。 你可以选择 n 的 二进制表示 中任意一个值为 1 的位&#xff0c;并将其改为 0。 返回使得 n 等于 k 所需要的更改次数。如果无法实现&#xff0c;返回 -1。 示例 1&#xff1a; 输入&#xff1a; n 13, k 4 输出&#xff1a; 2 解释&#xff1a…

使用Docker Swarm进行集群管理

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用Docker Swarm进行集群管理 引言 Docker Swarm 简介 安装 Docker Ubuntu CentOS 初始化 Swarm 集群 加入 Worker 节点 验证集…

SPA和SSR

单页面应用程序(SPA) 单页面应用(SPA)全称是:Single-page application, SPA应用是在客户端呈现的(术语称:CRS)。 SPA应用默认只返回一个空HTML页面&#xff0c;如:body只有<div id"app"></div>而整个应用程序的内容都是通过JavaScript动态加载&#xf…

初始JavaEE篇——多线程(4):wait、notify,饿汉模式,懒汉模式,指令重排序

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;JavaEE 目录 wait、notify 方法 多线程练习 单例模式 饿汉模式 懒汉模式 指令重排序 wait、notify 方法 wait 和 我们前面学习的sleep…

MySQL-基础汇总

MySQL-基础汇总 数据库对于任何一个从事后台开发的人说都是永远躲不掉的&#xff0c;任何系统或程序离开了数据的支持都变的毫无意义。而管理数据的工具——数据库就显得尤为重要。本章节我们的核心就是 MySQL&#xff0c;相信很多小伙伴跟我一样&#xff0c;也沉浸在增、删、…

【AD】1-2 AD24软件的中英文版本切换

1.如图设置软件后&#xff0c;关闭软件重新打开。如果想要切换回英文&#xff0c;将③勾选去掉&#xff0c;关闭软件重新在打开即可。

CSS、Less、Scss

CSS、Less和SCSS都是用于描述网页外观的样式表语言&#xff0c;但它们各自具有不同的特点和功能。以下是对这三者的详细阐述及区别对比&#xff1a; 详细阐述 CSS&#xff08;Cascading Style Sheets&#xff09; 定义&#xff1a;CSS是一种用来表现HTML或XML等文件样式的计算机…

【Python项目管理】“无法创建虚拟环境”报错原因及解决方法

一、问题说明 笔者最近在做一个python项目&#xff08;使用pycharm IDE&#xff09;&#xff0c;在添加python解释器时&#xff0c;提示无法创建虚拟环境&#xff08;Unable to create virtual environment&#xff09;&#xff0c;如下2图所示&#xff1a; 【添加python解释…

【实践】某央企研究院如何打造IT监控告警平台?

01客户简介&#xff1a; 案例客户为某央企下属研究院。 02痛点分析&#xff1a; 随着信创国产化持续推进&#xff0c;案例客户已完成部分IT核心系统的替代&#xff0c;部署了一系列国产软硬件设施&#xff0c;如Kylinv10操作系统、融智通网络设备等。由于信创生态不够成熟&a…

qt QBrush详解

1、概述 QBrush是Qt框架中的一个基本图形对象类&#xff0c;它主要用于定义图形的填充模式。QBrush可以用于填充如矩形、椭圆形、多边形等形状&#xff0c;也可以用于绘制背景等。通过QBrush&#xff0c;可以设置填充的颜色、样式&#xff08;如实心、渐变、纹理等&#xff09…

0-1规划的求解

实验类型&#xff1a;◆验证性实验 ◇综合性实验 ◇设计性实验 实验目的&#xff1a;学会使用Matlab编程实现求解0-1规划。 实验内容&#xff1a;1.学习使用Matlab定义子函数的命令function&#xff1b; 2.编程求解0-1型整数规划的枚举法或隐枚举法。 例1&#xff1a;求…

禾川HCQ1控制器程序编译报错如何解决

1、第一次打开用户程序 2、提示库未安装 3、安装库文件 4、脉冲轴库未安装 5、没有错误 去禾川自动化官网,把可以安装的包和库都安装下,程序编译就没有错误了。 6、下载相关包文件

C++进阶-->AVL树的实现

1. AVL树的介绍 1、AVL树的名字来源于他的发明者G. M. Adelson-Velsky和E. M. Landis两个前苏联的科学家&#xff0c;他们名字首元素组成。 2、AVL树就是我们前面二叉搜索树实现的时候提到的平衡二叉搜索树即二叉搜索树的左右孩子都是AVL树&#xff0c;即左右子树的高度差的绝…

【网络安全】|nessus使用

1、扫描结果分析&#xff1a; Sev&#xff1a;漏洞的严重性级别 CVSS&#xff1a;量化漏洞严重性的标准&#xff0c;通过计算得出一个分数&#xff0c;分数越高表示漏洞越严重。 VPR&#xff1a;基于风险的评分系统&#xff0c;帮助组织优先处理风险最高的漏洞。 EPSS&#xf…

P2-5【C语言基本数据类型、运算符和表达式】第五节-知识要点:格式输出函数printf()

讲解视频&#xff1a; P2-5【C语言基本数据类型、运算符和表达式】第五节-知识要点&#xff1a;格式输出函数printf() 知识要点&#xff1a;格式输出函数printf()。 一、任务分析 已知三角形三边a&#xff0c;b&#xff0c;c的值&#xff0c;求三角形的面积。要求输出a&#…

RFID资产管理

随着物联网和智能制造的发展&#xff0c;RFID资产管理逐渐成为企业提升运营效率的重要工具。利用RFID技术&#xff0c;企业能够实时跟踪和管理各种固定资产&#xff0c;从而提高资产利用率&#xff0c;降低运营成本。在现代化的管理体系中&#xff0c;RFID资产管理不仅限于资产…

Vue2——单页应用程序路由的使用

一.单页应用程序与多页应用程序之间的比较 二.单页的应用场景 系统类网站 / 内部网站 / 文档类网站 / 移动端网站 三.路由的介绍 1. 什么是路由 路由是一种映射关系 2. Vue中的路由是什么 路径和组件的映射关系 四.VueRouter的使用 5个基础步骤&#xff08;固定&#xff09; …

苹果ipa上架apple store 遇到的问题汇总已经解决方案!

大家伙&#xff0c;我是小黄。 最近在将ipa上架到apple store的时候遇到了一些问题&#xff0c;经过很长时间的摸索和修改终于成功上架了&#xff0c;下面是我遇到的问题和解决过程&#xff0c;希望可以帮助到大家。 一&#xff1a; Guideline 1.3 - Safety - Kids Category …