- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我有一个具有专门化的模板类,在另一个文件中定义。因此,可以生成同一类的两个版本:一次通过替换模板参数,一次使用特化。我目前的理解是,这会导致同一类型的两个实例在内存中具有不同的大小,从而导致段错误。
我创建了一个最小示例,以下代码用于说明问题:
创建模板类:
// - templateexample.h ---------------
#ifndef TEMPLATEEXAMPLE_H
#define TEMPLATEEXAMPLE_H
template<typename T> class Example
{
public:
Example(){}
int doWork() {return 42;}
};
#endif
// -----------------------------------
另一个文件中的模板特化:
// - templatespecialization.h --------
#ifndef TEMPLATESPECIALIZATION_H
#define TEMPLATESPECIALIZATION_H
#include "templateexample.h"
template<> class Example<int>
{
public:
Example() : a(0), b(1), c(2), d(3) {}
int doWork() {return a+b+c+d;}
private:
int a; //<== the specialized object will be larger in memory
int b;
int c;
int d;
};
#endif
// --------------------------------
拥有一个仅包含模板类定义的类,但应该包含专门化。
// - a.h --------------------------
#ifndef A_H
#define A_H
#include "templateexample.h"
class A
{
public:
Example<int> returnSmallExample();
};
#endif
// - a.cpp ------------------------
#include "a.h"
Example<int> A::returnSmallExample() {return Example<int>();}
// --------------------------------
主类现在知道 Example<int>
的两个版本一个来自 A,一个来自 templatespecialization.h。
// - main.cpp ---------------------
#include <iostream>
#include "a.h"
#include "templatespecialization.h"
int main()
{
A a;
Example<int> test = a.returnSmallExample();
std::cout<<test.doWork()<<std::endl;
}
// --------------------------------
请注意,这个问题只会在单独编译类 A 时发生,这个来自 ideone 的示例输出 6,而使用单独的文件可能会导致段错误,或输出 42(https://ideone.com/3RTzlC)。 在我的机器上,示例编译成功并输出 2013265920:
在上述示例的生产版本中,所有内容都构建到一个供 main 使用的共享库中。
问题 1:为什么链接器没有检测到这个问题?通过比较物体的大小应该很容易发现这一点。
问题 2:是否有一种方法可以检查目标文件或共享库,以检测同一类型的多个实现,如上例所示?
编辑:请注意:上面的代码是解释问题的最小示例。出现这种情况的原因是模板类来自一个库,我无法编辑该库中的文件。最后整个东西在可执行文件的所有地方都被使用了,现在我需要查明是否出现了上述问题。
编辑:上面的代码可以这样编译:
#!/bin/bash
g++ -g -c a.cpp
g++ -g -c main.cpp
g++ -o test a.o main.o
最佳答案
您对同一模板及其在不同翻译单元的特化有不同的定义。这导致 One Definition Rule违规。
解决方法是将特化放在定义主类模板的同一个头文件中。
Question 1: Why doesn't the linker detect this problem? This should be easy to spot by comparing the size of objects.
不同的类型可能具有相同的大小(例如 double
和 int64_t
),因此,显然,仅比较对象的大小是行不通的。
Question 2: is there a way to examine the object files or the shared library to detect multiple implementations of the same type like in the example above?
你应该使用 gold linker用于链接您的 C++ 应用程序(如果您尚未使用它)。它的一个不错的功能是 --detect-odr-violations
命令行开关,它完全按照您的要求执行:
gold uses a heuristic to find potential ODR violations: if the same symbol is seen defined in two different input files, and the two symbols have different sizes, then gold looks at the debugging information in the input objects. If the debugging information suggests that the symbols were defined in different source files, gold reports a potential ODR violation. This approach has both false negatives and false positives. However, it is reasonably reliable at detecting problems when linking unoptimized code. It is much easier to find these problems at link time than to debug cases where the wrong symbol.
参见 Enforcing One Definition Rule了解更多详情。
关于c++ - 如何从模板特化中找到重复的定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27836712/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!