问题标签 [virtual-table]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
0 回答
259 浏览

c++ - C++多级继承thunk对象指针调整

考虑以下具有 3 级多重继承层次结构的代码。

此代码运行的输出如下:

这建议 BaseE obj 的以下内存布局(指针大小为 8 个字节)。


8 字节,BaseD 子对象,仅 vptr 到 D 表

8 字节,BaseA 子对象,vptr 只到 A 表

8 字节,BaseB 子对象,仅 vptr 到 B 表。

这里ePtrdPtr都指向BaseD子对象,aPtr和都cPtr指向子BaseA对象和bPtrBaseB对象。

我现在的问题是编译器将生成什么 thunk 代码来调整上述this两个调用中的指针以b()通过指针cPtrbPtr确保this正确指向ePtr何时调用BaseE的实现b()?由于cPtr并且bPtr具有不同的地址,thunk 是否需要注意根据传递给它的基类指针的类型进行不同的调整?

0 投票
0 回答
57 浏览

tsql - 虚拟表(又名视图)

我们使用基于云的系统来处理患者数据。该系统日志的供应商提供了一份他们的 SQL 数据库副本以供使用,我们在本地恢复它,以便我们进行报告。这些本地表被锁定并设置为只读。我们无法控制它。

现在是有趣的部分。我们将创建另一家隶属于我们的公司。基于云的供应商不能在同一个数据库上合并两家公司。这意味着我们将获得该新公司数据库的第二套副本。希望它们包含相同的物理布局,但根据我与供应商的经验,情况并非如此。

到目前为止,我们将 DB #1 称为“CompanyA” DB #2 称为“CompanyB”

它们的结构将是“相同的”。所以我们可以很容易地在两个数据库的对象之间进行联合。

出于报告目的,供应商建议我们使用他们的慢速定制视图。因此,无论我们用这些视图编写的任何代码,如果它们对其系统的内部表进行更改,它都不会中断。他们不索引视图,因此创建一个外部视图,在 CompanyA 和 CompanyB 下联合相同的视图效率不高。

创建一个暂存过程以仅提取我们使用的对象(表/视图)的数据是另一种选择,但我不喜欢在我们的系统中拥有重复数据的想法。

我们可以购买像 Denodo 这样的系统来进行数据虚拟化。该系统允许我们创建特殊视图(虚拟表)并将我们的报告或 ETL 指向这些虚拟表。例如,我们的 ETL 只看到一个患者表,但在其下方是来自 CompanyA.Patients 和 CompanyB.Patients 的数据的组合。

我们的最终目标是拥有一个可扩展的流程,以防我们的组织决定继续将公司添加到我们的投资组合中并将它们集成到我们的系统中,这不像我们现在所面临的挑战。

所以这是我最后的问题: 1- SQL Server 是否具有在最新版本上创建虚拟表的功能?2-还有其他推荐吗?

0 投票
2 回答
1250 浏览

c - 在不使用函数指针的情况下在 C 中引用虚拟表的替代方法。

我通过使用多态性(在 C 中)中描述的虚拟表来利用 C 中的多态性,它工作得很好。

不幸的是,我当前项目的限制不允许我在代码的某些部分中使用函数指针或对结构的引用。因此,我不能直接使用原始方法。

在上述方法中,基“类/结构”有一个指向虚拟表的成员。为了得到这个指针,我决定用一个枚举替换它,作为访问虚拟表的键。

它有效,但我想知道是否是最好的解决方案。你有没有比我的建议更适合的替代方案?

0 投票
3 回答
194 浏览

c++ - 为什么使用存储在虚方法表中的地址对虚函数的函数调用返回垃圾?

我从虚拟表中的地址调用虚拟函数作为练习来测试我对这个概念的理解。然而,当我以为我对虚拟方法表的理解有所突破时,我又遇到了另一个我只是不明白的问题。

在下面的代码中,我创建了一个名为的类Car,它包含一个成员变量 x 和两个虚函数,first 和 second。现在,我通过破解虚拟表来调用这两个虚拟方法。第一个函数返回正确答案,但第二个函数返回一些随机值或垃圾,而不是初始化时的值。

如果有人能指出我做错了什么,那将不胜感激。此外,由于这在编译器中的工作方式不同,我正在使用 c++14在http://cpp.sh/上对其进行测试。

该代码输出输出,其中“垃圾”第二个输出可能会发生变化:

0 投票
0 回答
40 浏览

sql - 在 T-SQL 的性能方面,什么更好?内部 + 子查询还是内部 + 虚拟表?

我对性能有疑问。

什么是更好的?

  1. 具有特定 WHERE 子句(表有索引)的多个嵌套内连接 + 子查询。
  2. 使用行数据创建一个虚拟表并将其与内部联接相关联?
0 投票
1 回答
115 浏览

c++ - 如何使用 vtable 将类实例正确写入和读取到 QSharedMemory?

我有一个从接口派生的类

现在我想编写一个程序,它将Implementer在所有应用程序实例中获取相同的类实例。我按照此处建议的示例(第二个)进行操作,但在该示例中,仅使用了一个字节。

第一个实例工作正常。但是第二个上线就崩溃了impl->foo()

我认为原因是void*Implementer*. 但我不知道如何正确地做到这一点。

有什么建议么?

编辑

我意识到,由分段错误引起的崩溃是继承的结果,因为没有基类,一切正常。

编辑 2

经过一些调试、内存转储和一些注释后,我意识到问题在于,在运行时程序的第一个实例vtable在其堆栈中创建了 并将其vptr放入vtable. 第二个实例得到相同的vptr结果,不幸的是,它指向一些随机内存(可能已分配或未分配)。

0 投票
2 回答
313 浏览

c++ - vptr 和 vtable 是从基类继承的吗?

可以看出,在继承链的中间D3引入了一个新的虚函数。@function3()我想知道发生这种情况时 *--vptr 和 vtable 会发生什么。D3 现在是“一种”新的基类,

https://imgur.com/a/sxFzrKG

但是当我看到 vtable 条目时,我能看到的是function1(), function2(). 我认为条目必须是function2(), function3()。为什么我不能得到我的想法?

0 投票
1 回答
830 浏览

sql - 仅使用另一个表的 rowid 创建虚拟表

假设我在 sqlite 中有一个表,如下所示:

我想使用最小的存储空间来存储下表的结果:

如何从这个结果集中存储一个虚拟表,它只会给我有序的结果集。换句话说,以有序的方式存储rowid(在上面它会是3,1)而不将所有数据保存到单独的表中。

例如,如果我以排序顺序仅使用 rowid 存储此信息:

然后我相信每次我需要查询时,vtable我都必须使用rowid. 有没有办法做到这一点,以便 vtable “知道”它基于外部表的内容(我相信在创建fts索引时这被称为外部内容 - https://sqlite.org/fts5 .html#external_content_tables)。

0 投票
0 回答
88 浏览

c++ - 读取 C++ vtable 的竞争条件。有可能吗?

我的应用程序有时会崩溃,因为_purecall正在调用 MS,但我在故障转储中看到的数据不是我所期望的。

CSocket派生自CConnection,后者有一个名为的纯虚函数DoRead,当一个实例CSocket在工作线程中调用此函数时,应用程序崩溃。

根据寄存器值以及 Microsoft 如何实现 C++ 虚拟表和调用,我看到RCX了正确的this值,第一个四字指向 v-table 并且 v-table 是正确的,因此_purecall不应发生调用。

但是在看到构造函数是如何实现的之后,我看到CConnection构造函数设置了指向 v-table 的指针,其中包括调用_purecall然后,CSocket的构造函数用正确/派生的 v-table 覆盖这个值。

这就是我怀疑正在发生的事情:

  1. 一个线程调用new CSocket.
  2. CSocket调用构造函数和修改 v-table 之前,工作线程读取指针附近的一些内存(可能是因为它正在处理其他CSocket实例的操作)并且该内存页面被处理器“缓存”。
  3. 线程创建CSocket继续其执行完成CSocket构造。
  4. 当工作线程访问 v-table 时,从“缓存”页面而不是包含正确 v-table 的真实内存中读取值。

乍一看,编译器没有插入内存屏障来避免这种情况。

我的假设是否正确?是否有可能发生或编译器/处理器有避免这种情况的机制?

0 投票
1 回答
90 浏览

c++ - 对于多态类型T,如何在没有T类型实例的情况下获取指向T的虚表的指针

我有一个具有单继承的继承层次结构,我想检查指向基址的指针指向的对象是否完全属于派生类型 T。

我写了两种方式并比较了汇编代码:

如果我们比较一下 test 和 test2 的汇编代码,我们可以看到如下:

-O3 处的 Clang 9.0.0

/O2 的 MSVC 19.22 更糟糕,因为它甚至无法内联对 typeid 比较的调用。

问题似乎是 typeid 在设计上被迫做我在特定上下文中不需要做的事情,例如空指针测试(以及通过异常进行错误处理)或实际上在内存中具有类型信息结构并加载进行比较。

但是,如果 T 不是默认可构造的,则 vtable_ptr 不起作用,如果优化器无法将 T 的实例化编译掉,则可能不会那么快,并且如果 T 的构造函数或析构函数具有副作用,则会以令人惊讶的方式表现。

问题是,有template <typename T> void const * vtable_ptr()没有不需要实例化 T 的实现方式?编译器显然知道此信息。您只需要查看它正在生成的程序集 ( mov eax, offset vtable for Derived+16)。问题是,作为程序员,我可以访问这些信息吗?