Are inline variables unique across boundaries?

ぐ巨炮叔叔 提交于 2019-11-29 05:34:39

This is how I interpret the standard. According to basic.link/1:

A program consists of one or more translation units linked together.

It doesn't say anything about static linking nor dynamic linking. A program is translation units linked together. It doesn't matter if the linking is done in two steps (first create a .dll/.so, and then the dynamic linker links all dynamic libs + executable together).

So, in my interpretation, it doesn't matter whether a program is dynamically or statically linked, the implementation should behave the same: a class static variable should be unique (no matter whether it's inline or not).

On Linux, this is true.

On Windows, this doesn't work in all circumstances, so in my interpretation, it violates the standard in these circumstances (if you create a separate .dll, which contains the static, non-inline variable, and all other .dll's and the exe refers to this variable, it works).

C++ currently does not have a concept of shared libraries. So the way inline behaves across shared libraries would be implementation- and platform-specific.

The fact that [basic.link]/1 states that "A program consists of one or more translation units linked together." doesn't quite mean that a program linked together with another, already linked module, should behave the same.

A lot of proposals have been submitted over the years to rectify the situation (N1400, N1418, N1496, N1976, N2407, N3347, N4028), none of which took off the ground. It's just hard to implement in a generic way, and C++ generally tries to stay out of implementation details. As GCC put it:

For targets that do not support either COMDAT or weak symbols, most entities with vague linkage are emitted as local symbols to avoid duplicate definition errors from the linker. This does not happen for local statics in inlines, however, as having multiple copies almost certainly breaks things.

MSVC does not expose any symbols by default. Any "external" symbol needs to be explicitly declared with a platform-specific __declspec(dllexport). One can't claim Windows to be incompatible with C++ because of this. None of C++ rules are violated here, because there aren't any.

Paul Sanders

Is there any guarantee regarding the uniqueness of an inline variable when it is used across boundaries or is it simply an implementation detail that I should not rely on?

It's up to you to ensure this (by making sure that all the declarations are in fact the same).

The compiler obviously can't check this and the linker doesn't bother. So if you lie to the linker (by not doing the above), then you will end up in trouble.


OK, since not everyone's getting what I mean by 'lie to the linker', I'll flesh it out a bit.

@oliv kindly supplied this link, which amongst other things says this (commentary mine):

Duplicate copies of these constructs [i.e. variables declare inline in multiple TU's] will be discarded at link time.

Which is fine, that's what we need. Thing is, you don't know which ones (obviously, only one is retained, so by extension, you don't know which one that will be).

So, if they differ, you don't know which one you're going to end up with and so what you end up with is (a particularly insidious form of) UB. That's what I meant by 'lie to the linker'. Because, by declaring your variables differently in different TU's, that's exactly what you did. Whoops!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!