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

2023-05-16

今天遇到一个很典型的因为没有留意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





本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐