Там любой g ++ опции, которые могут обнаружить неподходящую инициализацию станд.:: строка с ПУСТЫМ символом константы*?
Я был в процессе превращения некоторых международных полей в станд.:: строковые, т.е.:
struct Foo
{
int id;
Foo() : id(0) {}
};
... превращенный:
struct Foo
{
std::string id;
Foo() : id(0) {} //oooops!
};
Я полностью пропустил плохую 'идентификационную' инициализацию с 0, и g ++ не дал мне предупреждений вообще. Эта ошибка была обнаружена во время выполнения (станд.:: строковый конструктор выдал исключение), но я действительно хотел бы обнаружить такой материал во время компиляции. Есть ли какой-либо путь?
Я думаю, что на самом деле это неопределенное поведение и не проверяется компилятором. Вам повезло, что эта реализация вызывает исключение.
Однако вы можете избежать таких проблем, указав, что вы хотите инициализацию по умолчанию или нулевую инициализацию независимо от типа:
struct Foo
{
X id;
Foo() : id() {} //note empty parenthesis
};
Я не могу придумать способ обнаружить это во время компиляции, поэтому я написал функцию сборщика строк, которая правильно работает с нулевыми указателями:
// FUNCTION : safe_string(char const* pszS)
// PARAMATERS : pszS source string to build a string from (may be NULL or 0-length)
// DESCRIPTION : Safely builds a string object from a char*, even a NULL pointer
// RETURNS : string
template<class C>
inline basic_string<C> safe_string(const C* input)
{
if( !input )
return basic_string<C>();
return basic_string<C>(input);
}
Я использую это всякий раз, когда создаю строку, и есть вероятность, что входные данные могут быть NULL.
В GCC есть инфраструктура для выдачи именно такого предупреждения:
void foo(const char* cstr) __attribute__((nonnull (1)));
void bar() {
foo(0);
}
при компиляции с -Wnonnull
(что подразумевается -Wall
) выдает:
warning: null argument where non-null required (argument 1)
Поэтому в принципе вы должны иметь возможность изменить соответствующий системный заголовок (или, лучше для экспериментов, изменить свою собственную копию $HOME/bits/basic_string. h и затем переопределить системный с помощью -isystem $HOME
) подобным образом:
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
__attribute__((nonnull (1)));
Однако это не поможет, поскольку (по крайней мере, в 4.0.1) -Wnonnull
не поддерживается в C++, и атрибут, по-видимому, игнорируется. Неясно, почему это так; возможно, было сочтено, что он плохо взаимодействует с перегрузкой или что-то в этом роде.