结构体类型重声明导致的bug一个

Posted yutingliuyl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了结构体类型重声明导致的bug一个相关的知识,希望对你有一定的参考价值。

bug前提条件

当模块比較多。头文件较多,某个结构体类型会在当前模块中又一次声明进而引用其成员,而不直接包括其它模块的头文件。

这种优点是不引入不须要的类型声明到此模块。头文件包括的交叉;坏处是,添加了bug的几率,耦合太大!比方以下一种情况发生而导致bug:

已知两个模块A和B。同一个结构类型struct node在两个模块中分别声明。当中B模块无意或者有意调整了结构类型中的某些域。那么这个时候。若B模块中引用A模块中此类型实例然后訪问成员变量,就会引发bug!

例如以下重现演示样例

bug重现演示样例代码

moduleA.c

#include <stdio.h>
struct node{
	char *name;
	void *data;
};

//定义測试变量
struct node new = {
	"TuoLuoFuSiJi",
	NULL
};

//測试输出
extern test_output(void);
void output(void)
{
	printf("%s\n", new.name);	
}

int main(int argc, char *argv[])
{
	printf("call output:\n");
	output();
	printf("call test_output:\n");
	test_output();
	return 0;
}

moudleB.c

#include <stdio.h>
//这里又一次声明,调整域的顺序
struct node{
	void *data;
	char *name;
};

//引用moduleA中的new实例
extern struct node new;

void test_output(void)
{
	if(new.name)
		printf("%s\n", new.name);	
	else
		printf("name is null\n");
}
Makefile

run: moduleA.o moduleB.o
	cc -o run moduleA.o moduleB.o

运行结果:

技术分享


结果分析:

在模块B中,对name的訪问偏移量计算是根据本模块中的声明决定的。name的偏移量是4!

同理。在模块A中,name的偏移量是0.在模块B中訪问模块A中实例new时,

依照偏移量4计算。得到的确是data的值。显然为NULL。

解决的方法:

建议办法

1-往上提升;公共的类型声明。定义成一个全局性的头文件,多个模块共同使用。而不隶属与不论什么一方,避免交织

2-合作协商;两个模块的绝对一致。即一方改变(比方增删成员。或者改域名),必须通知还有一方

3-模块接口化。假设外面模块须要訪问本模块的实例。那么本模块应该提供接口。而不是让其它模块直接訪问自己模块的实例!这样是最理想的。

也符合高内聚,低耦合原则。

个人认为(3)是最理想的解决的方法。








以上是关于结构体类型重声明导致的bug一个的主要内容,如果未能解决你的问题,请参考以下文章

C 语言结构体 ( 结构体类型定义 | 结构体类型别名 | 声明结构体变量的三种方法 | 栈内存中声明结构体变量 | 定义隐式结构体时声明变量 | 定义普通结构体时声明变量 )

结构体全解,适合初学者的一条龙深度讲解(附手绘图详解)

C++ 结构体的声明

C 语言结构体 ( 结构体类型变量初始化 | 定义变量时进行初始化 | 定义隐式结构体时声明变量并初始化 | 定义普通结构体时声明变量并初始化 )

头文件重复包含

结构体对齐