码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 【C/C++】结构体中使用变长数组问题分析


    目录

      • 1. 问题来源
      • 2. 问题复现
        • 2.1 初始程序
        • 2.2 独立变长数组复现
        • 2.3 变长数组置前复现
        • 2.4 缓冲区溢出复现
      • 3. 结构体变长数组使用要点

    1. 问题来源

    今天在结构体里面使用变长数组来封装消息体,运行程序时弹出如下错误:

    *** stack smashing detected ***: <unknown> terminated
    Aborted (core dumped)
    
    • 1
    • 2

    问题已经解决,由于源程序不方便截取,现在通过一个实例来复现问题。


    2. 问题复现

    2.1 初始程序

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    typedef struct {
        int a;
        char body[];
    } msg_t;
    
    int main(void)
    {
        msg_t msg;
        char *pdu = "abcdefg";
        strcpy(msg.body,pdu);
        printf("msg body:%s\n",msg.body);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    上述程序编译是没有问题的,但如果带变长数组的结构体换两种写法,会复现两种错误。


    2.2 独立变长数组复现

    typedef struct {
        char body[];
    } msg_t;
    
    • 1
    • 2
    • 3

    结构体中只有变长数组body[],无其他成员。编译错误如下:

    test.c:7:10: error: flexible array member in a struct with no named members
         char body[];
    
    • 1
    • 2

    这种情况在实际中并不会出现,如果只有一个成员,就没必要多一层结构体。


    2.3 变长数组置前复现

    typedef struct {
    	char body[];
    	int a;
    } msg_t;
    
    • 1
    • 2
    • 3
    • 4

    变长数组body[]不为结构最后一个成员。编译错误如下:

    test.c:7:10: error: flexible array member not at end of struct
         char body[];
    
    • 1
    • 2

    这种情况就是按照C99标准变长数组必须是结构体的最后一个成员。


    2.4 缓冲区溢出复现

    运行编译出的可执行程序,打印错误如下:

    msg body:abcdefg
    *** stack smashing detected ***: <unknown> terminated
    Aborted (core dumped)
    
    • 1
    • 2
    • 3

    这里是因为没有为变长数组body分配内存,检测到了缓冲区溢出,通过如下表达式分配内存:

    msg_t *msg= (msg_t*)malloc(sizeof(msg_t)+16*sizeof(char));
    
    • 1

    这样就为结构体指针msg分配了一块内存空间,程序变为:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    typedef struct {
        int a;
        char body[];
    } msg_t;
    
    int main(void)
    {
        msg_t *msg = (msg_t*)malloc(sizeof(msg_t)+16*sizeof(char));
        char *pdu = "abcdefg";
    
        strcpy(msg->body,pdu);
        printf("msg body:%s\n",msg->body);
        free(msg);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    编译成功,运行结果正常:

    msg body:abcdefg
    
    • 1

    3. 结构体变长数组使用要点

    • 结构体中不能只有变长数组一个成员,同时变长数组必须为结构体最后一个成员。
    • 变长数组不占用结构体的存储空间,长度为0,数组名只是一个占位符。sizeof()计算结构体大小时,变长数组在其中长度为0。
    • 使用变长数组结构体时,用malloc()分配内存空间。使用完毕用free()可以直接释放整个结构体的空间。
  • 相关阅读:
    C++ Primer Plus 第七章笔记
    概率密度分布(distribution)的均值(期望)(mean)和中值中位数(median)
    【晚风摇叶之其他】抖音直播弹幕解析,连接websocket解析弹幕内容
    一个完整的测试过程一般包括哪些阶段?
    ASP.NET Core 6框架揭秘实例演示[41]:跨域资源的共享(CORS)N种用法
    删除pip下载的所有第三方库,最快的方法,没有之一
    IDEA插件开发(11)---插件配置文件
    【OpenCV】在MacOS上源码编译OpenCV
    Spring Cloud Gateway:打造可扩展的微服务网关
    【CSS3】CSS3 3D 转换 ① ( CSS3 3D 转换简介 | 3D 物体与 2D 物体区别 | 3D 空间坐标系 | 常用的 3D 转换属性 | 3D 位移转换语法 | 代码示例 )
  • 原文地址:https://blog.csdn.net/NoBack7/article/details/125529483
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号