所以我正在使用这个巨大的代码库,并意识到其中一个结构缺少一个重要的领域。我尽可能密切地查看代码(使用结构)并得出结论,添加一个额外的字段不会破坏它。
关于我可以搞砸的任何想法?
另外:欢迎设计建议 - 我能做到这一点的最佳方法是什么?
例如(如果我不清楚):
typedef struct foo
{
int a;
int b;
}
foo;
现在是:
typedef struct foo
{
int a;
int b;
int c;
}
foo;
答案 0 :(得分:6)
如果在任何地方对该结构进行序列化/反序列化,请务必注意代码的该部分。
仔细检查正在分配内存的代码区域。
答案 1 :(得分:4)
如果您使用sizeof(struct)在所有地方分配内存并使用 - >访问成员要么 。经营者,我认为你不应该遇到任何问题。但是,它还取决于您尝试添加成员的位置,如果您不小心,它可能会搞砸您的结构对齐。
答案 2 :(得分:4)
从你上面的内容我看不出有什么不对。我能想到的两件事:
c
吗?跟进:
由于你还没有找到错误,我会停止查看你的结构。有人曾经写过先寻找马,斑马第二。也就是说,错误可能不是一个奇特的错误。您在单元测试中的覆盖范围是多少?我假设这是遗留代码,几乎总是意味着0%或至少这是我的经验。这准确吗?
答案 3 :(得分:2)
关于我可以搞砸的任何想法?
无。一切。这一切都取决于使用方式,地点和原因。
假设你所说的这个结构是一个C风格的POD而且代码是最简单的,你就可以逃脱它。但是,当您尝试更具野心的事情时,您正在处理对齐问题(取决于您创建对象的方式和位置)以及至少填充。如果这是C ++并且您的POD包含自定义运算符/ ctors等 - 您将遇到很多麻烦。如果您依赖有关的字节序等,可能会出现跨平台问题。
答案 4 :(得分:1)
寻找memcpy, memset, memcmp
。这些功能不是成员。如果使用之前的结构长度使用它们,则可能会出现问题。
还搜索文件以查找struct
的每个实例。可能存在不使用新重要字段的功能或方法。正如其他人所说,如果你在#define
或typedef
中找到结构,你也必须搜索它们。
答案 5 :(得分:1)
因为您标记了问题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
而不破坏任何现有(已编译!)代码。
答案 6 :(得分:1)
如果代码有一套强大的单元测试,那么跟踪问题可能要容易得多(你要求设计建议;)
我假设您不需要在这个巨大的代码库中的任何地方使用新的'c'变量,您只是添加它以便在您添加或修改的某些代码中使用它?您可以创建一个包含foo对象和c的新结构bar,而不是将c添加到foo中。然后在需要的地方使用吧。
至于实际的错误,它可能是任何信息都很少的东西,但如果我不得不猜测,我会说有人在某处使用了魔法数字而不是sizeof()。
答案 7 :(得分:0)
如果代码用于通过网络传输数据,则可能会破坏事物。
答案 8 :(得分:0)
如果在第一个成员之外的任何地方添加结构成员会破坏任何内容,那么代码具有未定义的行为,这是错误的。所以至少你有其他人(或你的早期自己)应该为破损负责。但是,未定义的行为包括“碰巧做我们想做的事情”,正如其他人所说的那样,注意内存分配,序列化(网络和文件IO)。
顺便说一下,当我看到typedef FOO ... struct FOO时,我总是畏缩,好像有人试图使C代码看起来像C ++。我意识到我在这里属于少数人:)
答案 9 :(得分:0)
在C结构的末尾添加新元素总是安全的。将该结构传递给不同进程的事件。已经重新编译的代码将看到新的struct成员和尚未知道的代码将只知道旧的struct大小并且只读取它所知道的旧成员。 需要注意的是,新成员必须添加到结构的末尾而不是中间。