【问题标题】:Avoiding improper std::string initialization with NULL const char* using g++使用 g++ 使用 NULL const char* 避免不正确的 std::string 初始化
【发布时间】:2011-01-25 08:22:14
【问题描述】:

是否有任何 g++ 选项可以使用 NULL const char* 检测 std::string 的不正确初始化?

我正在将一些 int 字段转换为 std::string 字段,即:

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

...变成:

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

我完全忽略了使用 0 和 g++ 进行的糟糕的“id”初始化,根本没有给我任何警告。在运行时检测到此错误(std::string 构造函数引发异常),但我真的很想在编译时检测到这些东西。有什么办法吗?

【问题讨论】:

  • 不幸的是,0 是一个不会触发从 int 到指针的无效转换错误的值。因为当然 0 是一个空指针常量,所以可以转换为任何指针类型。除了像访问者所说的那样,我不知道您能做的任何事情,首先不要编写该初始化程序。
  • 正确的解决方案是添加一个私有构造函数std::string::string(int);。这将是一个更好的匹配,因此会导致编译时错误。
  • 不确定您是否是这个意思,但这可能确实有效,作为一次性测试来捕获从intstring 的这一轮更改导致的任何错误。修改 g++ 标准头文件中的std::basic_string,检查新代码是否可以编译,然后在任何人注意到之前快速改回来。
  • 哦,不改变标准头不是一个选项 :) 但我可能应该让 g++ 开发人员在未来添加私有 int 构造函数?

标签: c++ g++ stdstring


【解决方案1】:

我想不出在编译时检测到这一点的方法,所以我写了一个字符串生成器函数来正确处理空指针:

//  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 时,我都会使用它。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 嗯...所以您是说 int 类型的默认构造函数分配 0 ?
    • 这个语法意味着内置类型的零初始化。
    【解决方案3】:

    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++ 中不受支持,并且该属性显然被忽略了。为什么会这样并不明显。也许是感觉它与重载或其他东西的交互很糟糕。

    【讨论】:

    • 实际上你上面的basic_string ctor __attribute__((nonnull (1))) 检查this 指针不是NULL;只需更改为__attribute__((nonnull (2))) 以检查__s 是否为非空;见gcc.gnu.org/ml/gcc/2006-04/msg00549.html
    猜你喜欢
    • 2018-06-04
    • 2016-02-04
    • 1970-01-01
    • 2013-09-12
    • 2011-01-07
    • 1970-01-01
    • 1970-01-01
    • 2017-04-11
    • 1970-01-01
    相关资源
    最近更新 更多