在 Windows 中初始化静态全局变量时 new 返回 NULL?
Posted
技术标签:
【中文标题】在 Windows 中初始化静态全局变量时 new 返回 NULL?【英文标题】:new returns NULL when initializing static global variable in windows? 【发布时间】:2010-02-12 01:08:40 【问题描述】:我正在努力将 rLog 与我们的代码库集成,并且我注意到 Windows 上存在一个我在 linux 上没有的问题。在头文件中,我有一个静态变量,它为我提供了一个“详细”的日志记录通道(基本上从调试开始),因此定义:
static RLogChannel *rlog_verbose = DEF_CHANNEL("verbose", Log_Debug);
这在 Linux 上没有问题,但在 Windows 上,应用程序一启动就会出错。
我已经在 rLog 库中追踪到这一行:
RLogChannel *rlog::GetComponentChannel(const char *component, const char* path, LogLevel levl)
...
if(!gRootChannel)
gRootChannel = new RLogChannel( "", level );
...
问题是对 new 的调用返回了一个 NULL 指针,它没有被检查 并且程序在被访问时会立即崩溃。是否有与在 Windows 上的全局上下文中分配内存相关的规则?
编辑:我很确定这一定与静态对象的初始化顺序有关。我想确保我没有遗漏一些明显的内容:Windows 上的内存分配。谢谢大家!
【问题讨论】:
new
不能返回 null。你的意思是它抛出一个异常?
您是否检查过代码是否实际执行了,或者 gRootChannel 是否在其他地方只是 NULL?
这两段代码有什么联系?第一个变量名是rlog_verbose
,第二个变量名是gRootChannel
。有什么联系?有吗?
抱歉,更新得更清楚一点,代码的 sn-p 位于一个因使用 DEF_CHANNEL 宏而被调用的函数中。 @GMan:我不知道 new 抛出了异常,很高兴知道,但我看到对 0x00000000 的无效写入,所以它一定不是 new 调用。可能与静态初始化程序的顺序有关...
@GMan:在 Visual Studio 6 中,如果出现错误,new 会返回 NULL。 @gct:你用的是哪个版本的VS?
【参考方案1】:
你确定它返回 null。它可能是整个静态初始化器的事情。静态初始化程序调用的顺序没有在文件之间定义。如果您有使用 rlog_verbose 的静态代码,那么 gRootCHannel 很可能是 NULL,因为尚未调用初始化程序。
【讨论】:
【参考方案2】:new
不返回 NULL。如果失败,它会抛出 std::bad_alloc
异常。即使它在入口点 CRT 函数中实际调用的静态数据初始化中也会发生这种情况,该函数稍后会调用 main()
。
您看到的 NULL 可能就在那里,因为从未调用过 new
。要验证它是否真正被调用,您只需在静态初始化上放置一个断点并查看它何时发生。
【讨论】:
很高兴知道,我猜这是某种静态初始化问题,我只是很少有 Windows 经验,所以我想确保我没有遗漏一些明显的东西。【参考方案3】:new
不返回 null。所以你的问题一定是你在静态初始化程序执行之前使用了rlog_verbose
。您的静态初始化程序可能从不执行。 (那将是一个链接问题)
您需要启动一个调试器并在您的静态初始化程序、main
以及崩溃的代码行上设置一个中断,然后看看发生了什么。如果您跨过崩溃,它会起作用吗?崩溃发生在main
之前吗?
【讨论】:
以上是关于在 Windows 中初始化静态全局变量时 new 返回 NULL?的主要内容,如果未能解决你的问题,请参考以下文章