2010-03-09 36 views
10

有没有任何g ++选项可以检测不正确的初始化std :: string与NULL const char *?避免不正确的std ::字符串初始化与空const char *使用g ++

我是在转弯一些int字段成的std :: string的人的过程,即:

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

...变成了:

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

我完全忽略坏的 '身份证'用0和g ++初始化完全没有给我警告。这个错误是在运行时检测到的(std :: string构造函数抛出一个异常),但我真的很想在编译时检测这些东西。有什么办法吗?

+2

不幸的是,0是一个不会触发从int到指针的无效转换错误的值。因为0是一个空指针常量,所以可以转换为任何指针类型。除了像访问者说的那样,我不知道你能做的任何事情,而不是首先写出初始化器。 – 2010-03-09 11:23:32

+0

正确的解决办法是添加一个私有构造函数'std :: string :: string(int);'。这会更好地匹配,从而导致编译时错误。 – MSalters 2010-03-09 11:47:12

+1

不确定你是否以这种方式表示,但实际上它可以起到一次性测试的作用,可以捕获从“int”到“string”这一轮更改所导致的任何错误。修改g ++标准头文件中的'std :: basic_string',检查新代码是否编译,然后在任何人发布之前快速更改它。 – 2010-03-09 12:01:15

回答

5

我认为它实际上是未定义的行为,并没有被编译器检查。你很幸运,这个实现引发了一个异常。

但是,您可以通过指定要默认或类型无关的方式零初始化避免这样的问题:

struct Foo 
{ 
    X id; 
    Foo() : id() {} //note empty parenthesis 
}; 
+0

嗯...所以你说默认构造函数为int类型分配0? – pachanga 2010-03-11 17:46:05

+3

此语法表示内置类型的零初始化。 – visitor 2010-03-12 09:40:00

+0

感谢您的信息! – pachanga 2010-03-28 07:07:19

2

有基础设施的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 /位/ basic_string.h复制,然后覆盖系统中的一个与-isystem $HOME)相似:

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

但是这并没有帮助,因为C++不支持(至少在4.0.1)-Wnonnull,并且该属性显然被忽略。这并不是显而易见的原因。也许有人认为它与超载或某事有很大的相互作用。

+1

其实你上面的'basic_string' ctor'__attribute __((nonnull(1)))'检查'this'指针不是'NULL';只需改变为'__attribute __((nonnull(2)))'来检查'__s'是否为非空;请参阅http://gcc.gnu.org/ml/gcc/2006-04/msg00549.html – vladr 2012-03-11 03:50:51

7

我不能想办法在编译时检测到这一点,所以我写了一个字符串生成器功能,与空指针正常交易:

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