Как избежать неправильной инициализации std :: string с помощью NULL const char * с использованием g ++ - PullRequest
10 голосов
/ 09 марта 2010

А есть ли опции g ++, которые могут обнаружить неправильную инициализацию std :: string с NULL const char *?

Я занимался преобразованием некоторых полей int в std :: string, т. Е.

struct Foo
{
   int id;
   Foo() : id(0) {} 
};

... превратился в:

struct Foo
{
   std::string id;
   Foo() : id(0) {} //oooops!
};

Я полностью пропустил неправильную инициализацию 'id' с 0, и g ++ вообще не дал мне никаких предупреждений. Эта ошибка была обнаружена во время выполнения (конструктор std :: string вызвал исключение), но я бы очень хотел обнаружить такие вещи во время компиляции. Есть ли способ?

Ответы [ 3 ]

7 голосов
/ 09 марта 2010

Я не могу придумать, как обнаружить это во время компиляции, поэтому я написал функцию построения строк, которая правильно обрабатывает нулевые указатели:

//  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.

5 голосов
/ 09 марта 2010

Я думаю, что это на самом деле неопределенное поведение и не проверяется компилятором. Вам повезло, что эта реализация выдает исключение.

Однако вы можете избежать таких проблем, указав, что вы хотите использовать инициализацию по умолчанию или нулевую инициализацию без учета типа:

struct Foo
{
   X id;
   Foo() : id() {} //note empty parenthesis
};
2 голосов
/ 09 марта 2010

В 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) аналогично: 1010 *

basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
    __attribute__((nonnull (1)));

Однако это не помогает, потому что (по крайней мере, в 4.0.1) -Wnonnull не поддерживается в C ++, и атрибут, очевидно, игнорируется. Непонятно, почему это так; возможно, чувствовалось, что он плохо взаимодействовал с перегрузкой или чем-то еще.

...