正是这个话题所要求的.还想知道为什么非CRTP的常见例子没有提到virtualdtor.
编辑:伙计们,请发布关于CRTP问题,谢谢.
我正在尝试编写一个基本上像indianwebproxy一样工作的Http代理
所以我启动了qtcreator,但是我的一个类无法使用臭名昭着的错误进行编译:undefined reference to vtable for HttpProxyThreadBrowser.我无法弄清楚为什么这样做.我在Stackoverflow上阅读了类似的问题,显然问题是未定义的虚拟方法不纯,但我还没有声明任何虚函数.这是我的课
class HttpProxyThreadBrowser : public QThread
{
public:
HttpProxyThreadBrowser(QTcpSocket outgoingSocket,QTcpSocket browserSocket,QObject *parent = 0);
~HttpProxyThreadBrowser(){};
void run();
private:
QTcpSocket outgoingSocket;
QTcpSocket browserSocket;
};
Run Code Online (Sandbox Code Playgroud)
我在这里用pastebin定义了这个类,以免给你带来烦恼.不幸的是,我无法找出为什么vtable未定义.请协助.
httpproxythreadbrowser.cpp:5: undefined reference to `vtable for HttpProxyThreadBrowser
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud) 是否可以从 C# 调用函数到结构中的非托管函数(通过 VTable)。
例如,我正在挂接一个应用程序,我正在为每个类(应用程序的)重新创建结构。
public struct SomeStruct {
[FieldOffset(0x00)]
public IntPtr * VTable;
[FieldOffset(0x10)]
public uint SomeValue;
}
Run Code Online (Sandbox Code Playgroud)
然后,我通常这样做:
var * data = (SomeStruct*)(Address);
Run Code Online (Sandbox Code Playgroud)
我希望通过以下任一方式从结构的 VTable 调用函数
Invoke<delegate>(data->VTable[0x3C])(delegateArguments)
Run Code Online (Sandbox Code Playgroud)
或者
var eax = Invoke<Func<uint,uint>(data->VTable[0x3C])(arg1,arg2)
Run Code Online (Sandbox Code Playgroud)
此外,这是否可以有效地完成(因为这些 vtable 函数可以被多次调用)?
也许通过反射发射?
据我所知,每次调用Invoke<>func时,编组都必须创建委托函数。
使用 g++ 编译时,-fdump-class-hierarchy 以(或多或少)人类可读格式导出程序的虚表。但是,生成的文件仅包含有关 vtable 的信息,而不包含有关类布局本身的信息。我想获得我所有程序类的布局的完整列表。
clang 提供 -cc1 -fdump-record-layouts 参数来实现这一点。可以使用 -d1reportAllClassLayout 调用 MS 编译器。是否有任何 g++ 开关可以做到这一点?
我最近遇到了一个 C++ 面试问题,这让我很感兴趣:
假设您错误地将某个 C++ 成员函数声明为虚拟函数,但是(可能出于性能原因)您希望阻止编译器为该函数创建 v 表。也就是说,禁用动态函数绑定以支持静态绑定。
你将如何实现这一目标?另外,是否有一些 C++11 特定的方法来这样做?
这个问题被多次以类似的方式提出,例如在stackoverflow或forum.qt.io或qtcentre.org。问题是这个错误消息非常模糊,以至于一种解决方案无法应用于另一种场景。不过,大多数线程都在讨论中死掉了:-(
所以我在 Qt 应用程序中收到的完整错误消息是:
找不到“OneOfMyClasses”
值的虚拟表的链接器符号,而是找到“QString::shared_null”
OneOfMyClasses根据各种情况而变化,QString::shared_null对于我收到的所有错误保持不变。这是我的日志控制台的屏幕截图:
它发生的点是在当前位置之前的源代码行中的该函数中(黄色箭头):
因此,根据我进入的消息m_pStateWidget->insertNavLabel(...),错误消息打印在与 QString 类相关的 Qt 内的构造函数中的某个位置。所以我尝试了以下方法,将问题从该代码位置移开:
执行此操作时,我在下面的几行代码中收到相同的错误消息,消息中包含另一个类名,请注意 QString ::shared_null保持不变。
在我看来,我的记忆有某种损坏。
感谢您的任何提示或帮助!:-)
编辑:现在变得非常有趣。在打印消息之前我已经进入了每个函数,最终得到了这些错误消息:
在这个位置:
当我在 QtCreator 中浏览调用堆栈时,每次我在堆栈中选择另一个函数时,都会一次又一次地打印错误。
当我在 C++ 中定义类时,我总是将 dtor 定义为 virtual。这是我保护自己的方法,以防我编写继承类。
我想知道即使我不会继承该类,我是否也要支付性能开销。
例如:
class A final
{
A();
virtual ~A(){printf("dtor");}
};
Run Code Online (Sandbox Code Playgroud)
当我使用此类时,dtor 实际上会通过 vtable 调用还是会作为静态 dtor 实现?
令 vptr 为指向 vtable 的指针,该 vtable 随其类受虚拟函数约束的对象一起携带。
“vptr”的改变可能不是预期的行为。然而,这种更改不能被检测为非法内存访问,因为指针位于已分配内存的边界内。据我所知,“Efence”和“valgrind/memcheck”不会有帮助。
然而,意外的 vptr 更改可能会导致严重的问题。如果 vptr 被更改为指向任意内存,则删除运算符可能会立即导致分段错误。
是否有任何东西可以在 vtable 或指向 vtable 的指针上设置“守卫”,以便监视任何更改?
Clang++ 似乎并没有完成全部工作。给定
#include <string.h>
#include <stdio.h>
struct X { virtual ~X() {} };
int main(int argc, char** argv)
{
X x;
memset((void*)&x, 0, sizeof(X));
printf("<before exit>\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译并执行...
> clang++ -fsanitize=undefined -fsanitize=vptr tmp.cpp -o test
> ./test
Run Code Online (Sandbox Code Playgroud)
在调用“virtual ~X()”时检测违规行为。
<before exit>
<unknown>: runtime error: member call on address 0xbfe30ab8 which does not point to an object of type 'X' …Run Code Online (Sandbox Code Playgroud) 如何创建多个类来充当接口类的实现者,同时尽可能避免 v-table 成本,并且仍然启用对接口的静态转换?
对于一个简单的情况,它可以像下面的例子一样实现。
图书馆代码:-
class I{ //interface
public: virtual void i1()=0;
};
template<class Derived>class Router : public I{
public: virtual void i1()final{
//in real case it is very complex, but in the core is calling :-
static_cast<Derived*>(this)->u1();
}
};
Run Code Online (Sandbox Code Playgroud)
用户代码:-
class User : public Router<User>{
public: void u1(){ std::cout<<"hi"<<std::endl; }
};
int main() {
User u;
u.i1(); //<-- no v-table cost
I* i=&u;
i->i1(); //<-- has v-table cost (OK)
}
Run Code Online (Sandbox Code Playgroud)
如何扩展上述功能以支持 2 …
我在 IAR 中有以下类结构:
class A
{
public:
A(){}
virtual ~A() {};
virtual void load() {};
};
class C
{
public:
C()
{
//C does other stuff, not relevant
}
};
class D;
class B : public A
{
public:
B() : invert(false) {};
virtual ~B() {};
void load()
{
//Irrelevant stuff done here
}
private:
C member_c;
std::vector<D*> vector_of_d;
struct {
bool var_1:1;
bool var_2:1;
bool var_3:1;
bool var_4:1;
bool invert:1;
};
};
Run Code Online (Sandbox Code Playgroud)
我遇到了为初始化 B 而生成的程序集的错误,它似乎对 VTable 指针的位置与匿名结构位域的位置感到“困惑”。当它设置反转位为假时,它转到对象的第一个字(即 VTable 指针)并翻转地址中的一个位。当我稍后调用 …