C++结构体中变长数组的使用问题分解刨析

 更新时间:2022年08月12日 09:03:13   作者:柒号华仔  
变长数组在C++中指的是集合(也叫容器)如vector就是C语言中,所有的数组都不定长,没有下标越界的概念,数组实质就是一个指针(由数组名充当)因此C语言中数组的长度没有任何意义平常在C语言中讲的不定长数组,其实就是指针

1. 问题来源

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

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

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

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;
}

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

2.2 独立变长数组复现

typedef struct {
    char body[];
} msg_t;

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

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

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

2.3 变长数组置前复现

typedef struct {
	char body[];
	int a;
} msg_t;

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

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

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

2.4 缓冲区溢出复现

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

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

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

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

这样就为结构体指针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;
}

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

msg body:abcdefg

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

  • 结构体中不能只有变长数组一个成员,同时变长数组必须为结构体最后一个成员。
  • 变长数组不占用结构体的存储空间,长度为0,数组名只是一个占位符。sizeof()计算结构体大小时,变长数组在其中长度为0。
  • 使用变长数组结构体时,用malloc()分配内存空间。使用完毕用free()可以直接释放整个结构体的空间。

到此这篇关于C++结构体中变长数组的使用问题分解刨析的文章就介绍到这了,更多相关C++变长数组内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解进程同步与互斥机制

    详解进程同步与互斥机制

    进程同步是一个操作系统级别的概念,是在多道程序的环境下,存在着不同的制约关系,为了协调这种互相制约的关系,实现资源共享和进程协作,从而避免进程之间的冲突,引入了进程同步
    2021-06-06
  • 利用C语言实现经典多级时间轮定时器

    利用C语言实现经典多级时间轮定时器

    C语言是一门通用计算机编程语言,广泛应用于底层开发,这篇文章主要给大家介绍了关于利用C语言实现经典多级时间轮定时器的相关资料,需要的朋友可以参考下
    2021-07-07
  • C++实现学生信息管理系统(完整版)

    C++实现学生信息管理系统(完整版)

    这篇文章主要为大家详细介绍了C++实现学生信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • C++归并排序算法实例

    C++归并排序算法实例

    这篇文章主要介绍了C++归并排序算法实例,本文先是介绍了什么是归并排序,然后给出了实现代码,需要的朋友可以参考下
    2014-10-10
  • c++中移动语义和完美转发及易错点

    c++中移动语义和完美转发及易错点

    C++ 中的移动语义和完美转发是 C++11 引入的两个重要特性,它们分别用于提高性能和灵活性,这篇文章主要介绍了c++中移动语义和完美转发,需要的朋友可以参考下
    2023-09-09
  • 手把手教你如何优化C语言程序

    手把手教你如何优化C语言程序

    程序进行优化,通常是指优化程序代码或程序执行速度。优化代码和优化速度实际上是一个予盾的统一,一般是优化了代码的尺寸,就会带来执行时间的增加,如果优化了程序的执行速度,通常会带来代码增加的副作用,很难鱼与熊掌兼得,只能在设计时掌握一个平衡点
    2013-07-07
  • 对C++ string append方法的常用用法详解

    对C++ string append方法的常用用法详解

    今天小编就为大家分享一篇对C++ string append方法的常用用法详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-06-06
  • 排序算法模板实现示例分享

    排序算法模板实现示例分享

    这篇文章主要介绍了排序算法模板实现示例,需要的朋友可以参考下
    2014-03-03
  • Cocos2d-x UI开发之CCControlColourPicker控件类使用实例

    Cocos2d-x UI开发之CCControlColourPicker控件类使用实例

    这篇文章主要介绍了Cocos2d-x UI开发之CCControlColourPicker控件类使用实例,本文代码中包含大量注释来讲解CCControlColourPicker控件类的使用,需要的朋友可以参考下
    2014-09-09
  • C语言小项目计时器的实现思路(倒计时+报警提示)

    C语言小项目计时器的实现思路(倒计时+报警提示)

    这篇文章主要介绍了C语言小项目计时器(倒计时+报警提示)的实现思路,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-11-11

最新评论