来自库代码的 init_seg 和警告 C4073? [英] init_seg and warning C4073 from library code?

查看:43
本文介绍了来自库代码的 init_seg 和警告 C4073?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个 C++ 库.它有四个对初始化顺序敏感的静态对象(其中两个是标准库中的字符串).

We have a C++ library. It has four static objects that are sensitive to initialization order (two of them are strings from the standard library).

我们正在使用 init_seg(lib) 控制库中C++静态对象的初始化顺序.使用它的源文件被编译并在动态链接库或静态库中使用.根据 init_seg 的文档:

We are using init_seg(lib) to control the order of initialization of C++ static objects in the library. The source file that is using it is compiled and used in either a dynamic link library or static library. According to the documentation for init_seg:

... 在需要初始化的动态链接库 (DLL) 或库 中使用 init_seg 编译指示尤为重要.(强调我的)

... It is particularly important to use the init_seg pragma in dynamic-link libraries (DLLs) or libraries requiring initialization. (emphasis mine)

Visual Studio 解决方案分为四个项目.一个是静态库,或者说是动态库,一个是静态库的测试驱动,一个是动态库的测试驱动.

The Visual Studio solution is organized into four projects. One is the static library, or is the dynamic library, one is the test driver for the static library, and one is the test driver for the dynamic library.

在 Visual Studio 下,使用 init_seg 编译源文件会导致 警告 C4073,文本初始化程序放在库初始化区域.根据 MSDN:

Under Visual Studio, compiling the source file with the init_seg results in warning C4073, with the text initializers put in library initialization area. According to MSDN:

只有第三方库开发者才能使用库初始化区,该区由#pragma init_seg 指定.以下示例生成 C4073...

Only third-party library developers should use the library initialization area, which is specified by #pragma init_seg. The following sample generates C4073...

使用init_seg 的代码仅用于库中,用于测试驱动程序.我已经验证了静态库和动态库项目设置,他们清楚地调用了库工件.

The code using the init_seg is used in the libraries only, and not used with the test drivers. I've verified the static library and dynamic library project settings, and they are clearly calling out library artifacts.

为什么我会收到 C4073 警告?

Why am I receiving the C4073 warning?

推荐答案

这只是警告你,连动手指都没有,更像是你确定吗?"当您使用使用此功能的 3rd 方库时,它也会警告其开发人员 - 除非他使用 #pragma warning 将其关闭.你也可以这样做.或者您可以使用user 段而不是lib 段:您的字符串仍将在您的 应用程序代码运行之前构造.Segment lib 真正适用于......哦,Qt 或 MFC 或类似的框架,需要在任何应用程序代码运行之前进行初始化,包括您的早期初始化user 中的内容.

It's just warning you, not even a wag of the finger, it's more like "are you sure?" When you use a 3rd party library that uses this feature it warned its developer too - unless he turned it off with #pragma warning. You could do the same. Or you could use segment user not segment lib: your strings will still be constructed before your application code runs. Segment lib is really intended for things like ... oh, Qt or MFC or a framework like that that needs to be initialized before any application code runs, including your early initialization stuff in user.

以下是更多信息:

假设您有一个自己的应用程序库.它有一些需要在运行任何代码之前初始化的东西,因为这个库公开的某些类旨在(或允许)在您的应用程序代码中静态分配,而这些类做复杂的事情在他们的构造函数中,比如说,需要一些大量预先计算的(但不是静态的)数据.因此,对于那些预先计算的东西,您在一个类(一个不同的类)的构造函数中预先计算它,然后静态分配该类的一个实例,以便该实例的初始化调用其预先计算所有这些东西的构造函数,而该静态实例您用 pragma init_seg(user) 标记.现在,在您的任何应用程序代码运行之前 - 包括代码中该库类的静态实例的任何构造函数 - 库的 init_seg(user) 代码都将运行,因此,当您的静态这个库的类的实例被构建,它们需要的数据就会在那里.

Suppose you have a library for your own app. And it has some stuff that needs to be initialized before any of its code is run, because certain classes exposed by this library are intended to be (or, are allowed to be) statically allocated in your application code, and those classes do complicated stuff in their constructors that needs, say, some large bollix of precomputed (but not static) data. So for that precomputed stuff you precompute it in the constructor of a class (a different class) and you statically allocate an instance of that class, so that the initialization of that instance calls its constructor which precomputes all that stuff, and that static instance you mark with pragma init_seg(user). Now, before any of your application code runs - including any constructors of static instances of this library's class in your code - the library's init_seg(user) code will all run, and so, by the time your static instances of this library's classes get constructed the data they need will be there.

现在考虑确实必须尽早存在的东西,其中存在可以调用的静态实例.例如,std::cout.您可以在您拥有静态实例的类的构造函数中调用 std::cout 上的方法.显然,对象 std::cout 需要在任何代码运行之前初始化.您的某些代码可能会在您标记为 init_seg(user) 的内容中运行.所以微软把所有这样的代码——也就是std::cout等的构造函数——放在init_seg(compiler)中.那些东西会在任何事情之前运行.

Now consider stuff that really has got to be there early, of which static instances exist that you can call. E.g., std::cout. You can call methods on std::cout in constructors of your own classes that you have static instances of. Obviously, the object std::cout needs to be initialized before any of your code runs. And some of your code might run in stuff you've marked init_seg(user). So Microsoft places all such code - that is, the constructors for std::cout etc. - in init_seg(compiler). That stuff will run before anything else.

那么 init_seg(lib) 是干什么用的?好吧,假设您是一个类似 MFC 的框架.您公开诸如 Application 对象之类的东西,用户将(可能会,预计会)为其创建静态实例.应用程序中将在静态初始化时运行的一些代码取决于 MFC 中需要初始化的其他内容.很明显它需要init_segged,但在哪里?compiler 仅用于编译器和运行时,您的框架内容 (MFC) 可能会在允许用户使用的 init_seg(user) 中使用...所以你得到了 compileruser 之间的中间级别——也就是 lib.

So what is init_seg(lib) for? Well, suppose you're a framework like MFC. You expose stuff like the Application object that the user will (is likely to, is expected to) create a static instance of. Some of the code in Application which will be run at static initialization time depends on other stuff in MFC that needs to be initialized. So obviously it needs to be init_segged, but where? compiler is for the compiler and runtimes alone, and your framework stuff (MFC) might be used in the init_seg(user) that the user is allowed to use ... so you get an intermediate level between compiler and user - that's lib.

现在很少需要这样的东西,因为程序使用的大多数 C++ 库本身并没有被多个库使用,因此不需要确保它们在所有其他普通"库之前被初始化.MFC 确实如此,因为您可能从一个或多个供应商那里购买了 3rd 方 MFC 控件或其他库,并且那些依赖于 MFC,并且那些可能在其构造函数中使用 MFC 的东西,并且您可能静态地使用这些库中的对象,因此 MFC 需要在其他库之前初始化.

Now it is fairly rare to need anything like that because most C++ libraries used by programs are not themselves used by multiple libraries and thus don't need to make sure they're initialized before all other "ordinary" libraries. MFC does, because you might have bought 3rd party MFC control or other libraries from one or more vendors, and those depend on MFC, and those might use MFC things in their constructors, and you might use objects from those libraries statically, so MFC needs to be initialized before those other libraries.

但在大多数情况下,您的库不会依赖于人们正在使用的其他 C++ 库.因此,没有任何类型的依赖链需要在其他库之前初始化您的库.您的库可能需要在您的用户代码之前进行初始化,是的,但没有任何需要初始化的顺序.所以 init_seg(user) 对他们所有人都很好.

But in most cases, your library isn't going to be a dependency of other C++ libraries that people are using. Thus there isn't any kind of dependency chain where your library needs to be initialized before other libraries. Your libraries might need to be initialized before your user code, yes, but there isn't any order in which they need to be initialized. So init_seg(user) is fine for all of them.

而且,Microsoft(通常还有大多数 C++ 专家)会告诉您:如果存在某种顺序依赖性,您的独立库需要在静态时初始化初始化您的应用程序 那么您就做错了.严重地.那里存在设计问题.

And, Microsoft (and generally, most C++ experts) will tell you: If there is some kind of order dependency in which your separate libraries need to be initialized at the time of static initialization of your app then you're doing it wrong. Seriously. There's a design problem there.

所以,回应评论:这不是编译器错误.这是用户警告.相当良性:如果你忽略它就不会出错(不像,说忽略关于从 long 到 int 转换的警告).但是如果您使用 init_seg(lib),您可能不会真正理解编译器功能的全部内容,因此他们希望您考虑一下.在您考虑之后,如果您仍然想这样做,请继续关闭警告.

So, to respond to a comment: It isn't a compiler bug. It's a user warning. Fairly benign: Nothing's going to go wrong if you ignore it (unlike, say ignoring a warning about casting from long to int). But if you're using init_seg(lib) you might not really be understanding what that compiler feature is all about, so they'd like you to think about it. And after you've thought about it, if you still want to do it, go ahead and turn the warning off.

这篇关于来自库代码的 init_seg 和警告 C4073?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆