c ++静态初始化命令fiasco

时间:2014-06-18 23:45:50

标签: c++ const static-members static-initialization static-order-fiasco

我目前正在学习C ++,而且我遇到了一些麻烦。

我使用大量#define开发了一个程序,但我想改用static const(碰撞/类型/范围......)。

所以,我现在有类似的东西:

file1.hpp

 class A {
   public:
     static const std::string MY_CONST_VAR;
 };

file1.cpp

 const std::string A::MY_CONST_VAR = "some string";

file2.cpp

 static std::string arrayOfString[] = {
   A::MY_CONST_VAR,
   ...
  };

我的代码编译时没有警告/错误(使用-W -Wall -Wextra -Werror标志进行编译)。

但是,当我尝试运行它时,会导致段错误。

我和valgrind一起跑了,它给了我以下的输出:

==11239== Invalid read of size 4
==11239==    at 0x5F525CB: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==11239==    by 0x40D076: _GLOBAL__sub_I__ZN16GraphicInterface13DEFAULT_WIDTHE (GraphicInterface.cpp:42)
==11239==    by 0x51AC7C: __libc_csu_init (in /home/simon/PSU_2013_zappy/gui/gui_zappy)
==11239==    by 0x66D8E54: (below main) (libc-start.c:246)
==11239==  Address 0xfffffffffffffff8 is not stack'd, malloc'd or (recently) free'd

因此,在arrayOfString实例化期间发生了段错误。我认为问题是arrayOfInt是在常量之前分配的。但在这种情况下,是否可以为此目的使用静态const?

我不知道如何修补此问题。 我做错了吗?有没有更好的方法呢?如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

static-init-fiasco问题的一般解决方法是将静态包装在函数中,因为函数内部的变量在调用函数之前不会对其初始值设定项进行求值。

当数组的长度由初始化器的数量决定时,这并不是那么简单。但是,恕我直言,访问全局C风格的数组是一个糟糕的设计:每次使用数组时都要用范围检查污染代码,否则你可能会冒险进行越界访问;和数组绑定错误是在运行时调试最难的错误之一。

我个人用代码替换代码:

std::string &lookup_string(size_t n)
{
    static std::string arrayOfString[] = { A::MY_CONST_VAR(), .... };

    if ( n >= dimof(arrayOfString) ) throw....
    return arrayOfString[n];
}

如果constexpr不可用,那么在另一个文件中:

std::string MY_CONST_VAR() { return "some string"; }

现在没有静态的惨败。

NB。我假设你想要arrayOfString的写访问权,因为你没有声明它const。如果它们应该是只读的,那么可以进一步改进。

答案 1 :(得分:2)

感谢您的评论,我终于使用constexpr关键字解决了这个问题。

它给了我以下工作代码:

file1.hpp

class A {
  public:
    static constexpr char MY_CONST_VAR[] = "some string";
};

file1.cpp

const char A::MY_CONST_VAR[];

file2.cpp

static std::string arrayOfString[] = {
  A::MY_CONST_VAR,
  ...
};