我正在处理一个庞大的代码库,发现其中一个结构体缺少一个重要字段。我尽可能仔细地查看了使用该结构体的代码,并得出结论:添加额外的字段不会破坏它。
你有什么想法是我可能搞错了哪里吗?
此外:欢迎提供设计建议 - 我最好的实现方式是什么?
例如:(如果我没有表达清楚):
typedef struct foo
{
int a;
int b;
}
foo;
现在是:
typedef struct foo
{
int a;
int b;
int c;
}
foo;
我正在处理一个庞大的代码库,发现其中一个结构体缺少一个重要字段。我尽可能仔细地查看了使用该结构体的代码,并得出结论:添加额外的字段不会破坏它。
你有什么想法是我可能搞错了哪里吗?
此外:欢迎提供设计建议 - 我最好的实现方式是什么?
例如:(如果我没有表达清楚):
typedef struct foo
{
int a;
int b;
}
foo;
typedef struct foo
{
int a;
int b;
int c;
}
foo;
如果该结构在任何地方进行了序列化/反序列化,请确保注意代码的该部分。
仔细检查内存分配的代码区域。
如果你在所有地方使用sizeof(struct)来分配内存,并使用->或.操作符访问成员,我认为你不应该遇到任何问题。但是,这也取决于你尝试添加成员的位置,如果不小心可能会破坏结构对齐。
后续:
既然你还没有找到错误,我建议你停止查看你的结构体。有人曾经说过,首先找马,其次找斑马。也就是说,错误可能不是一种奇异的错误。你的单元测试覆盖率有多少?我假设这是遗留代码,几乎肯定意味着0%或至少是我的经验。这准确吗?
有没有想过可能是哪里出了问题?
没问题,但也有问题。这完全取决于使用方式、地点和原因。
假设你所说的结构是 C 风格的 POD,并且代码非常简单,那么你可以轻松应对。但是,一旦你尝试更具野心的东西,你就会遇到对齐问题(取决于如何创建对象和位置)以及至少填充问题。如果这是 C++ 并且你的 POD 包含自定义运算符/构造函数等 - 你会遇到很多麻烦。如果你依赖字节序,可能会出现跨平台问题。
既然你的问题标记为C++:
未来,Pimpl/d-Pointer是一种策略,它允许您在扩展或重新设计类时拥有更大的自由度,而不会破坏兼容性。
例如,如果您最初编写了
// foo.h
class Foo {
public:
Foo();
Foo(const Foo &);
~Foo();
int a() const;
void a(int);
int b() const;
void b(int);
private:
class FooPrivate *const d;
};
// foo.c
class FooPrivate {
public:
FooPrivate() : a(0), b(0) {}
FooPrivate(const FooPrivate &o) : a(o.a), b(o.b) {}
int a;
int b;
};
Foo::Foo() : d(new FooPrivate()) {}
Foo::Foo(const Foo &o) : d(new FooPrivate(*o->d)) {}
Foo::~Foo() { delete d; }
int Foo::a() const { return d->a; }
void Foo::a(int a) { d->a = a; }
// ...
你可以很容易地将其扩展到
// foo.h
class Foo {
public:
// ...
int a() const;
void a(int);
int b() const;
void b(int);
int c() const;
void c(int);
// ...
};
// foo.c
class FooPrivate {
// ...
int a;
int b;
int c;
};
// ...
使用Foo
而不破坏任何现有(已编译的)代码。
查找 memcpy, memset, memcmp
。这些函数不是逐成员的。如果使用以前的结构长度使用它们,可能会出现问题。
还要搜索文件中每个 struct
的实例。可能有一些函数或方法没有使用新的重要字段。正如其他人所说,如果在 #define
或 typedef
中找到该结构,则必须搜索这些内容。
typedef struct FOO ... FOO
同样是毫无意义的,因为struct FOO
已经使得FOO
可以在没有struct
前缀的情况下使用。 - ephemient在C结构体的末尾添加新元素总是安全的,即使该结构体被传递给不同的进程。已重新编译的代码将看到新的结构体成员,而未重新编译的代码仅知道旧的结构体大小并读取其了解的旧成员。 这里需要注意的是,新成员必须添加在结构体的末尾而不是中间。