如何更改静态链接库中 const 字符串数组的 Visual Studio C++ 初始化序列

Posted

技术标签:

【中文标题】如何更改静态链接库中 const 字符串数组的 Visual Studio C++ 初始化序列【英文标题】:How to change Visual Studio C++ initialization sequence for const string arrays in statically linked libraries 【发布时间】:2014-02-24 13:10:47 【问题描述】:

我正在对 Visual Studio 2013 中的旧应用程序 (CWinApp) 进行一些更改,该应用程序使用旧的静态链接库。我在应用程序中初始化 const 字符串数组时遇到问题。

为了让事情变得更简单,我创建了一个基本示例来演示该问题。该示例包含一个引用静态库 MyLib.lib 的 CWinApp 应用程序(类 CTestApp)。 CTestApp 拥有在 MyLib 中定义的 MyClass 类型的对象。以下是一些代码摘录:

主应用程序(CTestApp)

TestApp.h:

class CTestApp : public CWinApp

   // --- Standard Wizard generated CWinApp stuff here ---
private:
   MyClass mine;
;

TestApp.cpp:

// --- Standard Wizard generated CWinApp stuff here ---

CTestApp::CTestApp()
   : mine(55)


静态库 (MyLib.lib)

MyClass.h:

#pragma once

#include <string>

const std::string ids[] =

   "ABC",
   "DEF",
   "GHI"
;
const int num_ids = 3;

class MyClass

public:
   MyClass(int id);
private:
   int id;
   std::string name;
;

MyClass.cpp:

#include "MyClass.h"

MyClass::MyClass(int id)
: id(id)

   for (int i = 0; i < num_ids; ++i)
   
      name += ids[i];
   

问题是当通过CTestApp::CTestApp 进入MyClass::MyClass 时,我发现数组ids 中的字符串是空的。同样奇怪的是,整数常量num_ids 被初始化为3,正如预期的那样。这似乎只发生在静态库中声明的 const 字符串数组。如果我在CTestApp 本身中声明一个类似的数组,它会在我进入CTestApp::CTestApp 时被初始化。

我还发现,如果我运行应用程序并中断CTestApp::InitInstance,则ids 已正确初始化。

有没有办法强制Visual Studio在进入CTestApp::CTestApp的成员初始化部分之前初始化像这样的const字符串数组?

【问题讨论】:

【参考方案1】:

不是真的。不过,您可能可以解决您的具体情况。

ids 是一个动态初始化的全局变量。

您的全局 CTestApp 对象也是如此。

ids 在包含标头的任何地方都被定义。 app 对象可能在某个主文件中定义。

C++ 未指定不同模块(.cpp 文件)中全局变量的动态初始化顺序。它可能因编译而异,因编译器而异。你不想依赖它。

如果需要保证顺序,唯一的办法就是把初始化放到同一个模块中。单个模块按声明顺序初始化。

因此,针对您的特定情况的解决方案是:在标题中将 ids 声明为 extern,并在之前将其与全局 app 一起定义。但是,这并不会随着您获得更多课程而扩展。

或者,通过将ids 更改为const char* 的数组,使ids 成为真正的常量。这将使其静态初始化,这发生在动态初始化之前。

最后,您可以将mine 更改为(智能)指针,并仅在InitInstance 中对其进行初始化。

【讨论】:

这是对(有点)常见问题的解决方案的一个很好的总结。我通常会选择const char * 感谢 Sebastian,您提供了一些不错的选择。尽管为了简单起见,我在问题中使用了字符串数组,但我正在处理的遗留代码实际上包含一大堆 const 结构数组,每个数组初始化中都声明了常量字符串。我发现通过在结构定义中将string 更改为const char *,我能够通过非常小的代码更改来解决问题。在这个阶段,我更改代码越少越好。

以上是关于如何更改静态链接库中 const 字符串数组的 Visual Studio C++ 初始化序列的主要内容,如果未能解决你的问题,请参考以下文章

如何利用Vue.js库中的v-html指令添加html元素

MSVS 链接器在静态 const 字符串之间添加数据

链接到静态库中的 explicit_bzero (glibc)

如何在 Swift 中声明一个静态 const char 数组? [关闭]

如何使静态库中的 gcc 链接强符号覆盖弱符号?

从 plist 加载的 iOS 静态 const 数组