前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一次紧急线上事故引发的严重问题

一次紧急线上事故引发的严重问题

作者头像
用户9831583
发布2022-06-16 16:41:46
2830
发布2022-06-16 16:41:46
举报
文章被收录于专栏:码出名企路

整个过程大概是这样的:

甲方和乙方接口需要数据传输,比如 甲方AA传递到乙方BB,乙方想用甲方AA中的数据,由于某方后期修改了自己的定义,导致sizeof不统一,整个系统发生了崩盘,引发了一次严重的线上事故。

甲方AA:

代码语言:javascript
复制
typedef struct aa
{
    int id;
    char a[6];
    enum day{
        one,
        two,
        three =4,
        four = 12
    };     
    double w;   
    float h;     
    long g;   
}AA;

乙方BB:

代码语言:javascript
复制
typedef struct bb
{
    int id;
    char a[3];
    enum day{
        one,
        two,
        three =4,
        four = 100
    }; 
    double w;           
    float h;    
    long g;
}BB;

双方通信:

代码语言:javascript
复制
 AA aa = {1,"wxh",2.2,3.3,4321};

  BB bb = *(BB*)(&aa);
  cout<<sizeof(AA)<<" "<<sizeof(BB)<<" "<<aa.h<<" "<<bb.h<<endl;

  memcpy(&bb,&aa,sizeof(aa));
  
  cout<<sizeof(AA)<<" "<<sizeof(BB)<<" "<<aa.h<<" "<<bb.h<<endl;

结果:

40 32 3.3 -1.58819e-23 40 32 3.3 -1.58819e-23

#pragma pack(1) //1字节对齐

30 27 3.3 4.47049e-08 30 27 3.3 4.47049e-08

本来甲方传了一个 3.3,而乙方得到的确是越界的负值 ,引发了系统崩溃。

类型

32位

64位

char

1

1

int

4

大多数4,少数8

short

2

2

long

4

8

float

4

4

double

8

8

指针

4

8

enum

4

4

对齐原因:

1,性能问题:数据结构尽可能在自然边界上对齐,若访问未对齐的内存,处理器需要作两次内存访问,而对齐的内存只要访问一次。

2,空间问题:没有进行内存对齐的结构体或类会浪费一定空间,当创建对象越多时,消耗的空间也越多。

3,平台问题:不是所有的硬件平台都能访问任意地址上的任意数据的,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

对齐规则:

struct:

1,结构体变量中成员的便移量必须是成员大小的整数倍数;

2,结构体大小必须是最宽基本类型大小的整数倍。

union:

1,所有成员中最长的那个;

2,整个结构体大小必须是最宽成员大小的整数倍。

enum:

1, 定义一个常量集合,当int存储,都为4。

因此:在定义结构体成员时为节省内存,一般将同一类型定义在一起,长类型放在最开始或者最后。

附:struct与union相互嵌套的技巧

代码语言:javascript
复制
#include <stdlib.h>
#include <stdio.h>
 
// 参考 Glibc库源码 sig_info.h
typedef struct info{
  int age;
  union {
    int code;
    struct {
      int pid;
      int uid;
    } id;
    struct {
      int KM;
      char *addr_name;
    } address;
  } u;
} info_t;
 
#define code     u.code
#define pid     u.id.pid
#define uid      u.id.uid
#define KM      u.address.KM
#define addr_name   u.address.addr_name
 
int main(int argc, char **argv)
{
  info_t info;
  
  info.age   = 20;
  info.code   = 5;
  
  printf("age = %d\n", info.age);      // 20
  printf("code = %d\n", info.code);    // 5
  
  printf("----------------------\n");
  info.pid = 123;
  printf("age = %d\n", info.age);      // 20
  printf("code = %d\n", info.code);    // 123, 因为code变量与id变量共用一块内存
  printf("pid = %d\n", info.pid);      // 123
 
  printf("----------------------\n");
  info.KM = 789;
  printf("age = %d\n",  info.age);    // 20
  printf("code = %d\n", info.code);    // 789, 因为code变量与address变量共用一块内存
  printf("pid = %d\n",  info.pid);    // 789, 因为id变量与address变量共用一块内存
  printf("KM = %d\n",   info.KM);      // 789
  return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码出名企路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档