- 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/
我想知道如何考虑需要您做出某些选择才能看到最终结果的搜索系统。我说的是 select 表单,您可以在其中根据您的选择继续操作,然后您会看到结果。 下面描述了我正在谈论的一个随机示例。想象一下 Init
您好,我目前正在编写一些软件来管理我们的库存。我搜索了 2 个表 master_stock(保存每一个股票代码和描述)库存(保存库存代码、地点、数量...) 一切都很好,但这是我遇到的问题。 假设我的
我有 2 个表,我想合并其数据。id 是我的关键字段(增量且不同)。表1和表2字段说明例如:id - 名称 - 值 我想将表2的所有数据插入表1,它们有不同的数据,但在某些行中有相同的id。 所以当我
我正在努力解决汇编中的一个问题,我必须获取十六进制代码的第一个字节 (FF) 并将其复制到整个值中: 0x045893FF input 0xFFFFFFFF output 我所做的
我有 Eclipse Indigo 版本,我可以在其中运行 Java 和 C++ 项目。 但我只想使用另一个 Eclipse 来编写 C++ 项目。所以我将 eclipse(不是工作区)的源文件夹复制
This question already has answers here: What is a NullPointerException, and how do I fix it? (12个答案)
This question already has answers here: Numbering rows within groups in a data frame (8个答案) 5个月前关闭。
我知道用q记录到寄存器中,但我想知道是否可以设置一些东西来快速调用最后一个记录,就像一样。 回顾最后一个简短的编辑命令(有关 的讨论请参阅 here。)。 我知道@@,但它似乎只有在执行@z之后才起作
来自 Eclipse 并且一直习惯于复制行,发现 Xcode 没有这样的功能是很奇怪的。或者是吗? 我知道可以更改系统范围的键绑定(bind),但这不是我想要的。 最佳答案 要删除一行:Ctrl-A
假设我有一个包含元素的列表,例如[1,2,3,4,5,6,7,8]。我想创建长度为 N 的该元素的所有排列。 因此,对于N = 4,它将是[[1,1,1,1],[1,1,1,2],[1,1,2,1],
我有一个带有 JMenu 的 JFrame。当我在某些情况下添加包含图像的 JPanel 时,程序首次启动时菜单会重复。调整大小时重复的菜单消失。任何建议都非常感激。谢谢。代码如下: public c
我正在尝试查找目录中文件的重复项。 我对这个 block 有一个问题,它以文件地址作为参数: public void findFiles(ArrayList list){ HashMap hm
我知道这个问题已经发布并且已经给出了答案,但我的情况不同,因为我在单个方法上填充多个下拉列表,所以如果我点击此链接 After every postback dropdownlist items re
我正在尝试为我的日历应用程序实现重复模式。我希望它的工作方式与 Outlook 在您设置重复约会时的工作方式相同。 public async Task> ApplyReccurrencePeriod
我有一个利用 cookie 来支持准向导的应用程序(即,它是一组相互导航的页面,它们必须以特定顺序出现以进行注册)。 加载 Logon.aspx 页面时 - 默认页面 - 浏览器 cookie 看起来
我有 3 个输入,代码检查它们是否为空,如果为空,则将变量值添加到输入中。 所以我有 3 个具有值的变量: var input1text = "something here"; var input2t
根据数组的长度更改数组的每个元素的最佳方法是什么? 例如: User #1 input = "XYZVC" Expected Output = "BLABL" User #2 input = "XYZ
我在让 Algolia 正常工作时遇到了一些麻烦。我正在使用 NodeJS 并尝试在我的数据库和 Algolia 之间进行一些同步,但由于某种原因似乎随机弹出大量重复项。 如您所见,在某些情况下,会弹
遵循以下规则: expr: '(' expr ')' #exprExpr | expr ( AND expr )+ #exprAnd | expr ( OR expr )+ #exprO
我有一个布局,我想从左边进入并停留几秒钟,然后我希望它从右边离开。为此,我编写了以下代码: 这里我在布局中设置数据: private void loadDoctor(int doctorsInTheL
我是一名优秀的程序员,十分优秀!