最近我们添加了2项新的警告到MSVC编译器中,用来提醒开发者错误地使用为编译器保留的二进制分区。在今天的这篇短文中,我们将会解释这两项警告的具体内容和它们会带来什么潜在的益处。听起来还不错,请继续阅读。
MSVCC++编译器提供了一些方法来创建不同的分区并将数据存放到这些分区中。链接器将会将它们转换为PE格式中的分区中。
此外,编译器还会为它自己创建一些分区。举个例子,[.CRT$XCU]这个分区就是编译器自己创建的,用来实现C++的动态初始化(当然还有其他分区也用来实现这个特性)。在”CRT初始化”相关的技术文档中,你可以查询到有关这个分区的细节内容。
有一些代码库会尝试模拟编译器的行为,但是它们使用的语法和编译器内部使用的不太一样。这通常会导致一些未定义的行为。在VisualStudiov16.11中,我们引入了两项默认的警告,它们分别是:C和C,专门用来对这种代码行为发出警告。
举个例子,我们在一些代码库中看到了如下的C++代码:
在上述代码中,有如下两个区别:1.[#pragmasection]创建的分区是一个常规分区,它与编译器为动态初始化创建的节具有不同的属性。2.放置在该分区的变量i是一个常规变量,不被编译器视为初始化程序。
以上这些区别可能导致更多语法上的细微差别,例如:1.变量i可能会被优化掉。2.相对于其他C++动态初始值设定而调用f的顺序会变为未指定的。3.用户定义的部分[.CRT$XCU]分区将干扰C++动态初始化。这可能导致未定义的行为,包括缺少初始化。
如果调用顺序不是那么重要,则我们建议使用以下的代码作为替代:
如果你需要指定一个特别的调用顺序(例如在任何编译器生成C++动态初始值设定项之前或之后),则没有一个标准的的方法来做到这一点。但是,你可以利用链接器中的一项功能,该功能按名称对部分进行排序,并避免使用由编译器创建或由CRT库使用的任何部分的名称(请注意,该变量可能仍会被优化掉,并且无法保证链接器行为在未来将保持不变),如下图所示:
请注意,虽然名称[.CRT$XCT]和[.CRT$XCV]目前未被编译器或CRT库所使用,但不能保证它们将来不会被使用。
总结
如果不是必须的话,还是需要谨慎使用#pragmasection。至少需要明白它的原理之后,再使用。
最后
MicrosoftVisualC++团队的博客是我非常喜欢的博客之一,里面有很多关于VisualC++的知识和最新开发进展。大浪淘沙,如果你对VisualC++这门古老的技术还是那么感兴趣,则可以经常去他们那(或者我这)逛逛。本文来自:《NewCompilerWarningsforDynamicInitializationandUserDefinedSections》
最近我写了个东西
正如你们所知道的,拓扑梅尔智慧办公平台(TopomelBox)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。我想:你值得拥有。