Я работаю над созданием Cppcheck для AIX с компилятором xlC
(см. предыдущий вопрос). Все классы проверки являются производными от класса 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.
Check
, и потомки предоставят значение во время построения. Сделайтеname()
не виртуальным и верните значение, переданное конструктором. Остальная часть конструктораCheck
, показанного здесь, может оставаться как есть. - person Rob Kennedy   schedule 02.02.2011