您的位置:首页 > 其它

常见的内存错误【三】

2006-11-27 20:38 323 查看
7. 结构的成员顺序变化引发的错误

在初始化一个结构时,老手可能很少像新手那样老老实实的,一个成员一个成员的为结构初始化,而是采用快捷方式,如:

Struct s
{
int l;
char* p;
};

int main(int argc, char* argv[])
{
struct s s1 = {4, "abcd"};
return 0;
}

以上这种方式是非常危险的,原因在于你对结构的内存布局作了假设。如果这个结构是第三方提供的,他很可能调整结构中成员的相对位置。而这样的调整往往不会在 文档中说明,你自然很少去关注。如果调整的两个成员具有相同数据类型,编译时不会有任何警告,而程序的逻辑上可能相距十万八千里了。
正确的初始化方法应该是(当然,一个成员一个成员的初始化也行):

struct s
{
int l;
char* p;
};
int main(int argc, char* argv[])
{
struct s s1 = {.l=4, .p = "abcd"};
struct s s2 = {l:4, p:"abcd"};
return 0;
}

8. 结构的大小变化引发的错误

我们看看下面这个例子:

struct base
{
int n;
};
struct s
{
struct base b;
int m;
};

在OOP中,我们可以认为第二个结构继承了第一结构,这有什么问题吗?当然没有,这是C语言中实现继承的基本手法。
现在假设第一个结构是第三方提供的,第二个结构是你自己的。第三方提供的库是以DLL方式分发的,DLL最大好处在于可以独立替换。但随着软件的进化,问题可能就来了。
当第三方在第一个结构中增加了一个新的成员int k;,编译好后把DLL给你,你直接给了客户了。程序加载时不会有任何问题,在运行逻辑可能完全改变!原因是两个结构的内存布局重叠了。解决这类错误的唯一办法就是全部重新相关的代码。
解决这类错误的唯一办法就是重新编译全部代码。由此看来,DLL并不见得可以动态替换,如果你想了解更多相关内容,建议阅读《COM本质论》。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: