Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 静态变量未初始化-有时?_C++ - Fatal编程技术网

C++ 静态变量未初始化-有时?

C++ 静态变量未初始化-有时?,c++,C++,我有一个智力游戏。拼图是使用拼图引擎ID从脚本文件创建的。拼图引擎使用静态散列中的静态变量进行注册。我收到了关于崩溃的报告,我们已经找到了没有特定密钥的散列的问题,它应该由静态函数添加 请注意,这是一个我们无法重现的bug,也就是说,该方法通常都是有效的。事实上,我不知道为什么有时候它显然不是。有没有可能不调用这些静态函数?也许是编译器的错误?(Visual C++ 2005)< /P> 拼图工厂类型 class PuzzleMode; typedef PuzzleMode* (*fnPuzzl

我有一个智力游戏。拼图是使用拼图引擎ID从脚本文件创建的。拼图引擎使用静态散列中的静态变量进行注册。我收到了关于崩溃的报告,我们已经找到了没有特定密钥的散列的问题,它应该由静态函数添加

请注意,这是一个我们无法重现的bug,也就是说,该方法通常都是有效的。事实上,我不知道为什么有时候它显然不是。有没有可能不调用这些静态函数?也许是编译器的错误?(Visual C++ 2005)< /P> 拼图工厂类型

class PuzzleMode;
typedef PuzzleMode* (*fnPuzzleFactory)(bool* bVictory, const char* sPuzzleCode, const GFC::StringList& lParams);
引擎使用此宏确保它们已注册。有一个静态bool,它作为注册工厂并返回true的函数的结果进行初始化:

#define REGISTER_PUZZLE(CODE, CLASSNAME)                                                                    \
    PuzzleMode* puzzleFactory##CLASSNAME (bool* bVictory, const char* sCode, const StringList& lParams)     \
    {                                                                                                       \
        return new CLASSNAME(bVictory, sCode, lParams);                                                     \
    }                                                                                                       \
                                                                                                            \
    static bool registerPuzzle##CLASSNAME (void)                                                            \
    {                                                                                                       \
        PuzzleMode::registerPuzzleFactory(CODE, puzzleFactory##CLASSNAME);                                  \
        return true;                                                                                        \
    }                                                                                                       \
                                                                                                            \
    static bool s_bRegisteredPuzzle##CLASSNAME = registerPuzzle##CLASSNAME();
例如,在puzzle engine.cpp中:

REGISTER_PUZZLE("bloodcollection", BloodCollection);
在其他地方,在.cpp中:

static Hash<String, fnPuzzleFactory>* s_hPuzzleFactories = NULL;

void PuzzleMode::registerPuzzleFactory (const char* sId, fnPuzzleFactory pFactory)
{
    if (!s_hPuzzleFactories)
        s_hPuzzleFactories = new Hash<String, fnPuzzleFactory>();   

    String sLowId = String(sId).lower();
    s_hPuzzleFactories->setAt(sLowId, pFactory);
}
静态哈希*s_hPuzzleFactories=NULL;
无效拼图模式::registerPuzzleFactory(常量字符*sId,FNpuzzFactory pFactory)
{
if(!s_hPuzzleFactories)
shpuzzlefactories=新哈希();
String sLowId=String(sId).lower();
s_hPuzzleFactories->setAt(斯洛维德,工厂);
}
所有这些都应该在应用程序启动时发生。很久以后它就这样被使用了

PuzzleMode* PuzzleMode::createPuzzleInstance (const char* sEngine, bool* bVictory, const GFC::StringList& lParams)
{
    // Shouldn't happen
    if (!s_hPuzzleFactories)
        s_hPuzzleFactories = new Hash<String, fnPuzzleFactory>();

    String sLowId = String(sEngine).lower();
        if (!s_hPuzzleFactories->hasKey(sLowId))    // <----- HERE
        return NULL;

    fnPuzzleFactory fnFactory = s_hPuzzleFactories->getAt(sLowId);
    return fnFactory(bVictory, sEngine, lParams);
}
puzzmode*puzzmode::createPuzzleInstance(const char*sEngine、bool*bVictory、const GFC::StringList&lParams)
{
//不应该发生
if(!s_hPuzzleFactories)
shpuzzlefactories=新哈希();
String sLowId=String(sEngine).lower();
如果(!s_hPuzzleFactories->hasKey(sLowId))//getAt(sLowId);
返回工厂(B工厂、sEngine工厂、lParams工厂);
}
有时,但只是有时,在上面标记的行中,哈希没有键


有什么想法吗?我能想到的唯一一件事(我在写这篇文章时想到的)是在哈希本身初始化为NULL之前调用register函数,但是在我们发现哈希没有我们要找的密钥之前,一切都应该崩溃并烧掉。

这可能是顺序问题。尝试将其重写为“”。

如果链接器认为编译单元不包含可访问的代码,则允许它完全删除编译单元。因此,如果.cpp文件中没有任何函数是从其他地方显式调用的,那么它可能会被完全丢弃,并且应该注册的对象只是从可执行文件中丢失


尝试在丢失的拼图的.cpp中放置一个伪外部函数,并从main()调用它,看看它是否解决了您的问题。

看起来这与静态初始化完全无关-在大量日志记录之后,我们发现一些不相关的代码显然正在破坏指针。

有趣。。。我会尝试你的建议。标准说:“在命名空间范围中定义的具有副作用的初始化的对象,即使没有使用,也必须初始化”,但这是假设该对象没有与编译单元的其余部分一起被丢弃。我身边没有标准,但我知道GCC至少做到了这一点——这是一个非常常见的陷阱。当GCC做到这一点时,它是不符合标准的。我们应该写一个bug报告:)看看3.7.1/2的草稿,我不确定它是bug,但不管它是不是bug,事实仍然是有几个编译器就是这样运行的(而且很糟糕!),这是一个合理的解释。静态对象只保证在第一次在翻译单元(TU)中调用函数之前进行初始化。如果在程序中的任何地方都没有调用TU的函数,则不需要创建对象。