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一个的更多相关文章

  1. 让结构体类型frame的某个属性可以直接修改

    本篇是是本人在博客园写的第一篇博客,前几天因为种种原因最终决定离开混了几年的csdn.希望在博客园有个新的开始 Foundation框架里面的frame是大家最熟悉不过的一个属性了,但是修改起来比较麻 ...

  2. typedef和自定义结构体类型

    在自定义结构体类型时会用到typedef关键字.大家都知道typedef是取别名的意思,在C语言中跟它容易混淆的有const,#define等,其区别不在本篇文章讨论之列. /*定义单链表结点类型*/ ...

  3. Go语言规格说明书 之 结构体类型(Struct types)

    go version go1.11 windows/amd64 本文为阅读Go语言中文官网的规则说明书(https://golang.google.cn/ref/spec)而做的笔记,介绍Go语言的 ...

  4. 张超超OC基础回顾03_结构体类型作为成员变量的特殊用法

    直接上例子: 要求: 合理的设计一个”学生“类 学生有* 姓名* 生日两个属性和说出自己姓名生日方法  要求利用设计的学生类创建学生对象,并说出自己的姓名和年龄 描述学生类 事物名称: 学生(Stud ...

  5. 自定义数据类型 C++ 结构体类型 共同体类型 枚举类型 类类型{}

    一.结构体类型 结构体类型,共用体类型,枚举类型,类类型等统称为自定义类型(user-defined-type,UDT). 结构体相当于其他高级语言中的记录(record);例如: struct St ...

  6. 你好,C++(14)如何描述“一个名叫陈良乔,年龄33岁,身高173厘米,体重61.5千克的男人”——3.8 用结构体类型描述复杂的事物

    3.8  用结构体类型描述复杂的事物 利用C++本身所提供的基本数据类型所定义的变量,只能表达一些简单的事物.比如我们可以用int类型定义nAge变量表示人的年龄,用string类型定义strName ...

  7. C语言中的系统时间结构体类型

    在C语言涉及中经常需要定时触发事件,涉及到获取系统时间,其结构体类型有多种.Unix/Linux系统下有以下几种时间结构: 1.time_t 类型:长整型,一般用来表示从1970-01-01 00:0 ...

  8. go语言进阶之为结构体类型添加方法

    1.为结构体类型添加方法 示例: package main import "fmt" type Person struct { name string //名字 sex byte ...

  9. OC对象里面包含的结构体类型的属性,不能对该结构体属性的成员单个进行修改

    OC对象里面包含的结构体类型的属性,不能对该结构体属性的成员单个进行修改,需要对OC对象的结构体属性整体赋值. 关于网上很多博客写着“结构体类型里面的某个属性如果想要修改是不允许单个修改的” 之解释: ...

随机推荐

  1. Liquibase简介(1)

    Liquibase是一个用于跟踪.管理和应用数据库变化的开源的数据库重构工具.它将所有数据库的变化(包括结构和数据)都保存在XML文件中,便于版本控制. Liquibase具备如下特性: * 不依赖于 ...

  2. 一些牛人的IOS博客,mark下慢慢学习

    http://blog.devtang.com/                  唐巧的个人blog http://gracelancy.com/     Lancy's blog http://b ...

  3. 将IP表存入SQL里的程序

    将IP表存入SQL里的程序 写得比較粗糙,另一点错误,只是能达到效果.请大家測试  create.asp  ---------------------------------------------- ...

  4. ZOJ 2588 Burning Bridges(求桥的数量,邻接表)

    题目地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2588 Burning Bridges Time Limit: 5 ...

  5. Linux系统病毒防治

    Linux系统病毒防治 一.Linux病毒的历史 1996年出现的Staog是Linux系统下的第一个病毒,它出自澳大利亚一个叫VLAD的组织.Staog病毒是用汇编语言编写,专门感染二进制文件,并通 ...

  6. AIX 系统补丁格式

    AIX 系统版本标准格式: 5300-06-11-0918 VR00-TL-SP-YYWW     5300-06-11-0918              ^-------- YYWW(2009年第 ...

  7. 外部数据库驱动程序XX中的意外错误

    链接EXCEL打开报错 代码如下(Excel2003版本)出现这种错误 现在只需要更改 修改成 并且把导入版本修改

  8. mkdi---创建目录。

    mkdir命令用来创建目录.该命令创建由dirname命名的目录.如果在目录名的前面没有加任何路径名,则在当前目录下创建由dirname指定的目录:如果给出了一个已经存在的路径,将会在该目录下创建一个 ...

  9. 兼容IE浏览器的canvas画线和圆圈

    1.新建test.html文件,代码如下: <!DOCTYPE html><html><head>    <meta charset="utf-8& ...

  10. 学习——HTML5

    HTML5多用于手机页面制作,因为PC版浏览器大多不兼容,可以通过下面网站查看HTML5浏览器兼容情况: http://www.caniuse.com/#index 一.语义化标签 1.<hea ...