一个对齐关键字pack引起的副作用

今天遇到一个很典型的因为没有留意pack关键字有效范围而引起的程序bug,觉得很有意思,就记录下来。

现象如下:声明了一个数据结构 struct st_data,这个数据结构中有一个成员是一个函数指针inic_cb,再定义一个函数st_data_constructor(st_data* my_data),在该函数中对my_data->inic_cb赋值,然后在main函数中定义struct st_data my_data变量,调用st_data_constructor(&my_data),然后再调用my_data.inic_cb();发现程序报了段错误。很奇怪,通过gdb调试时,发现进入st_data_constructor函数后,一切都很好,成员有被赋值,但是出了st_data_constructor函数重新进入main后发现,my_data.inic_cb的值十分怪异,很明显不是一个函数地址。被这个问题阻塞了很久,才突然灵光一现,是不是因为在main函数和st_data_constructor函数中的数据结构字节对齐不同(main函数和st_data_constructor函数处于两个不同的源文件,include了不同的头文件)。发现果然如此。

下面举一个例子说明

pack.h

#ifndef _PACK_H_
#define _PACK_H_

#pragma pack(1)

/*
Another code
*/
#endif

func.h

#ifndef _FUNC_H_
#define _FUNC_H_

typedef struct _st_sample_ {
    char flag;
    int value;
    char ext;
}st_sample, *p_st_sample;

void print_sizeof(p_st_sample p_sample);

#endif


func.c

#include <stdio.h>
#include <stdlib.h>
#include "func.h"

void print_sizeof(p_st_sample p_sample) {
    printf("%s: sizeof(st_sample): %ld\r\n", __FUNCTION__, sizeof(*p_sample));
}

main.c

#include <stdio.h>
#include <stdlib.h>
#include "pack.h"
#include "func.h"

int main(int argc, char* argv[]) { 
    st_sample sample;
    p_st_sample p_sample = &sample;
    printf("%s: sizeof(st_sample):%ld\r\n", __FUNCTION__, sizeof(*p_sample));
    print_sizeof(p_sample);

    return 0;
}
程序编译后,其结果如下:

./a.out 
main: sizeof(st_sample):6
print_sizeof: sizeof(st_sample): 12


可以看到,对同样的数据结构,其sizeof的值是不一样的。这样问题就很明显的显示出来了。

根本原因就是在pack.h中没有注意到#pragma pack(1)关键字的范围,实际上,我们不应该将pack.h中的#pragma pack(1)的作用范围暴露在该头文件之外。应该怎么做了?

修改pack.h文件如下

更正后的pack.h

#ifndef _PACK_H_
#define _PACK_H_

#pragma pack(1)

/*
Another code
*/

#pragma pack()
#endif
编译源代码后,执行结果如下:

./a.out 
main: sizeof(st_sample):12
print_sizeof: sizeof(st_sample): 12





  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值