gpt4 book ai didi

c++ - 我能保证不会被这种 ODR 违规行为所困扰吗?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:47:30 24 4
gpt4 key购买 nike

我有一个头文件,它声明了一个带有静态变量的模板并定义了它:

/* my_header.hpp */
#ifndef MY_HEADER_HPP_
#define MY_HEADER_HPP_

#include <cstdio>

template<int n>
struct foo {
static int bar;

static void dump() { printf("%d\n", bar); }
};

template<int n>
int foo<n>::bar;

#endif // MY_HEADER_HPP_

此 header 包含在 main.cpp 和共享库 mylib 中。特别是,mylib_baz.hpp 只包含此模板并声明一个修改模板特化的函数。

/* mylib_baz.hpp */
#ifndef MYLIB_BAZ_HPP_
#define MYLIB_BAZ_HPP_

#include "my_header.hpp"

typedef foo<123> mylib_foo;
void init_mylib_foo();

#endif // MYLIB_BAZ_HPP_

/* mylib_baz.cpp */
#include "mylib_baz.hpp"
void init_mylib_foo() {
mylib_foo::bar = 123;
mylib_foo::dump();
};

当我制作 mylib.so(包含 mylib_baz.o)时,foo<123>::bar 的符号存在并声明为弱。但是,foo<123>::bar 的符号在我的 main.o 中也被声明为弱:

/* main.cpp */
#include "my_header.hpp"
#include "mylib_baz.hpp"

int main() {
foo<123>::bar = 456;
foo<123>::dump(); /* outputs 456 */
init_mylib_foo(); /* outputs 123 */
foo<123>::dump(); /* outputs 123 -- is this guaranteed? */
}

看来我违反了一个定义规则( foo<123>::barmy_header.cppmain.cpp 中都有定义)。但是,对于 g++ 和 clang,符号都被声明为弱(或唯一),所以我不会被这个困扰——所有对 foo<123>::bar 的访问都修改同一个对象。

问题 1:这是巧合吗(也许 ODR 对模板的静态成员有不同的工作方式?)还是我实际上通过标准保证了这种行为?

问题 2:我如何预测我观察到的行为?也就是说,究竟是什么让编译器声明 symbol weak?

最佳答案

没有 ODR 违规。您有一个 bar 的定义。它在这里:

template<int n>
int foo<n>::bar; // <==

由于barstatic,这表明所有翻译单元都有一个 定义。尽管 bar 将在所有目标文件中出现一次(毕竟它们需要一个符号),链接器会将它们合并在一起成为 bar< 的一个真正定义。你可以看到:

$ g++ -std=c++11 -c mylib_baz.cpp -o mylib_baz.o
$ g++ -std=c++11 -c main.cpp -o main.o
$ g++ main.o mylib_baz.o -o a.out

产生:

$ nm mylib_baz.o | c++filt | grep bar
0000000000000000 u foo<123>::bar
$ nm main.o | c++filt | grep bar
0000000000000000 u foo<123>::bar
$ nm a.out | c++filt | grep bar
0000000000601038 u foo<123>::bar

u 表示:

"u"
The symbol is a unique global symbol. This is a GNU extension to the standard set of ELF symbol bindings. For such a symbol the dynamic linker will make sure that in the entire process there is just one symbol with this name and type in use.

关于c++ - 我能保证不会被这种 ODR 违规行为所困扰吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32656034/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com