简体   繁体   English

C ++字符串常量和静态变量初始化(或仅使用宏?)

[英]C++ string constants and static variable initialization (or just use macros?)

I am writing a library and wanted to be as C++ centric as possible, remembering the old adage "Macros are evil". 我正在写一个库,并想以C ++为中心,想起了古老的格言“宏是邪恶的”。

In a source file, I had the following definitions: 在源文件中,我具有以下定义:

const std::string DATA_DIR_ENV_STR = "DATADIR"
const std::string DFLT_DATA_DIR =  "../data"

/*
#define DATA_DIR_ENV_STR  "DATADIR"
#define DFLT_DATA_DIR  "../data"
*/


std::string getRootDirectory()
{
    char * datastr_ = getenv(DATA_DIR_ENV_STR);

    if (datastr_)
        return std::string(datastr_);
    return DFLT_DATA_DIR;
}

// Header file //头文件

std::string getRootDirectory();

I then had a singleton class that was initialized like this: 然后,我有一个单例类,其初始化如下:

bool mySingleton::inited = mySingleton::initialize();

bool mySingleton::initialize(){
   std::string rootdir = getRootDirectory(); // <-SEGV when using const std::string
}

The library compiled fine, but when I linked an application to it, the app always SEGV'd. 该库编译良好,但是当我将应用程序链接到它时,该应用程序总是SEGV。 I used gdb to track down the problem and to my shock/horror, the string variables DATA_DIR_ENV_STR and DFLT_DATA_DIR had not yet been initialized when they were been accessed during the static variable initialization. 我使用gdb来跟踪问题,并且令我震惊/震惊的是,在静态变量初始化期间访问字符串变量DATA_DIR_ENV_STR和DFLT_DATA_DIR时尚未对其进行初始化。

In the end I simply used macros to get around the issue. 最后,我只是使用宏来解决此问题。 BUT, I can't help wondering, is this a variation of the 'static variable initialization fiasco'?. 但是,我不禁要问,这是“静态变量初始化惨败”的变体吗? Is there another way to resolve this without using macros? 还有另一种无需使用宏即可解决此问题的方法吗?

It is a static initialisation issue, as you suspect. 您怀疑这是一个静态初始化问题。

I assume you use .c_str() in your getenv clause. 我假设您在getenv子句中使用.c_str()。

You could use const char * const rather than std::string in your statics. 您可以在静态变量中使用const char * const而不是std :: string。

namespace {
/*static*/ const char * const DATA_DIR_ENV_STR = "DATADIR";
/*static*/ const char * const DFLT_DATA_DIR = "../data";
}

Note use of anonymous namespace is generally preferred now to static. 请注意,现在通常首选使用匿名名称空间,而不是使用静态名称空间。

Your other option would be a function that returned them thus: 您的另一个选择是一个返回它们的函数:

namespace {
const std::string & DATA_DIR_ENV_STR()
{
  static std::string s("DATADIR");
  return s;
}

const std::string&  DFLT_DATA_DIR()
{
  static std::string s("../data");
  return s;
}
}

It is indeed a manifestation of that. 确实是这一点的体现。 See http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14 for more information (and below for solutions). 有关更多信息,请参见http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14 (有关解决方案,请参见下文)。

EDIT: Note that if you can redesign so that you don't need a singleton that will automatically fix the problem. 编辑:请注意,如果可以重新设计,则不需要单例即可自动解决问题。

Yes, this is the static initialization fiasco biting your behind. 是的,这是静态初始化惨败在后面。

A way to avoid it is the "construct on first use" idiom (brain-compiled code): 避免这种情况的一种方法是“首次使用时构造”惯用语(脑编​​译代码):

// In the header
class mySingleton {
    private:
        static mySingleton *s_instance;
        mySingleton();
    public:
        mySingleton &instance() {
            if (!s_instance)
                s_instance = new mySingleton();
            return *s_instance;
        }
};

// And in the source file...
mySingleton *mySingleton::s_instance;

However, in the case of string constants, you can also get away with simple char pointers: 但是,对于字符串常量,您还可以使用简单的char指针:

static char const *const DATA_DIR_ENV_STR = "DATADIR";
static char const *const DFLT_DATA_DIR = "../data";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM