这些MySQL类如何能够链接

How are these MySQL classes able to link?

本文关键字:何能够 链接 MySQL 这些      更新时间:2023-10-16

在内置MySQL存储引擎的实现中,存在具有以下结构的类:

// omitting lots of code across several files
class handler {
   protected:
      virtual void notify_table_changed();
};
void handler::notify_table_changed() {
   // implementation
}
class ha_innopart : public handler {
   void notify_table_changed();
};
// NB: no implementation for ha_innopart!

据我了解,这应该会产生链接错误,因为ha_innopart将缺少notify_table_changed()的 vtable 条目。这得到了 gcc 常见问题解答的支持。

指向相关 MySQL 类的链接:

  • handler.h : https://github.com/mysql/mysql-server/blob/67d52e7c7a1a23424e39273cbb6f5f9d56fda8d1/sql/handler.h#L3518-L3523
  • handler.cc : https://github.com/mysql/mysql-server/blob/67d52e7c7a1a23424e39273cbb6f5f9d56fda8d1/sql/handler.cc#L4736-L4744
  • ha_innopart.h : https://github.com/mysql/mysql-server/blob/67d52e7c7a1a23424e39273cbb6f5f9d56fda8d1/storage/innobase/handler/ha_innopart.h#L306-L307

如我所见,以下代码重现了该问题:

#include <stdio.h>
class A {
   public:
      virtual int foo();
};
class B : public A {
   public:
      int foo();               // Will work by commenting out this line...
};
int A::foo() { return 42; }
// int B::foo() { return 24; } // ...or uncommenting this line.
int main(int argc, char **argv) {
   B b;
   ::printf("%dn", b.foo());
}

编译它得到:

$ g++ test.cc -o test && ./test
/tmp/ccAiCHry.o: In function `main':
test.cc:(.text+0x32): undefined reference to `B::foo()'
/tmp/ccAiCHry.o: In function `B::B()':
test.cc:(.text._ZN1BC2Ev[_ZN1BC5Ev]+0x1f): undefined reference to `vtable for B'
collect2: ld returned 1 exit status

如上面的评论中所写,这个问题可以通过注释掉Bfoo()声明或通过为B提供foo()的实现来解决。这些案例的输出分别是:

$ !!
g++ test.cc -o test && ./test
42
$ !!
g++ test.cc -o test && ./test
24

那么,为什么MySQL没有实现ha_innopart::notify_table_changed()并且仍然能够编译和链接而不会出错呢?

事实证明,ha_innopart 的实现被分解在几个文件中,并且实现确实存在:

  • handler0alter.cc : https://github.com/mysql/mysql-server/blob/67d52e7c7a1a23424e39273cbb6f5f9d56fda8d1/storage/innobase/handler/handler0alter.cc#L8927-L8938

我在搜索用途时找到了实现。

https://github.com/mysql/mysql-server/search?utf8=%E2%9C%93&q=notify_table_changed