我正在构建 Cppcheck在 AIX 上使用 xlC
编译器(参见 previous question )。检查器类都派生自 Check
类,其构造函数在全局列表中注册每个对象:
check.h
class Check {
public:
Check() {
instances().push_back(this);
instances().sort();
}
static std::list<Check *> &instances();
virtual std::string name() const = 0;
private:
bool operator<(const Check *other) const {
return (name() < other->name());
}
};
checkbufferoverrun.h
class CheckBufferOverrun: public Check {
public:
// ...
std::string name() const {
return "Bounds checking";
}
};
我似乎遇到的问题是 instances().sort()
称呼。 sort()
会调用Check::operator<()
这叫Check::name()
在静态 instances()
中的每个指针上列表,但是 Check
刚刚添加到列表中的实例尚未完全运行其构造函数(因为它仍在 Check::Check()
中)。因此,调用 ->name()
应该是未定义的行为。在 CheckBufferOverrun
之前的这样一个指针上构造函数已完成。
这真的是未定义的行为,还是我在这里遗漏了一个微妙之处?
请注意,我不认为调用 sort()
是严格要求的,但效果是 Cppcheck 以确定的顺序运行其所有检查器。这只会影响检测到错误的顺序的输出,这会导致某些测试用例失败,因为它们期望以特定顺序输出。
更新:上面的问题仍然(大部分)成立。但是,我认为调用 sort()
的真正原因在构造函数中没有引起问题(即通过调用纯虚函数崩溃)是 Check::operator<(const Check *)
从未真正被 sort()
调用过!相反,sort()
似乎是比较指针。这发生在g++
和 xlC
,表明 Cppcheck 代码本身存在问题。
最佳答案
是的,它是未定义的。标准在10.4/6中特别这样说
Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined.
关于c++ - 从构造函数间接调用纯虚函数是否总是未定义的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4868226/