Duc*_*ers 4 c c++ struct ipc object
警告/免责声明:
这个问题包含了heresay,但在我过去半小时左右的小调查中,我无法找到以下声明的答案。我只是好奇这里是否有人已经知道这一点。
这个问题没有代码。只是技术问题。
背景:
我有一个遗留应用程序,它使用在进程之间传递的 C 样式结构进行进程间通信。这很有效,并且已经工作了很多年,甚至在我来到这个星球之前很久:P。
我应该编写一个新的流程来成为这个应用程序的一部分。不知不觉中,我用 C++ 编写了它,假设我们使用的任何 IPC 都可以处理这个问题。不幸的是,后来我(从同事那里)发现现有的基础设施只能传递 C 风格的结构体。
“未经证实”的声明/声明:
此外,一位同事列出了在这种情况下 C++ 是一个糟糕选择的以下原因。
C++ 对象有虚表。C 风格的结构只是变量和值。因此,C 风格的结构可以在进程之间传递,而 C++ 对象则不能。
使用 C 风格的结构,我们可以嵌入诸如结构大小之类的信息,这样双方都知道期望什么和发送什么,但对于 C++ 对象,这是不可能的,因为“vtable 的大小可能会有所不同”。
'如果我们改变编译器,那就更糟了。对于 C++ 对象,我们将有更多的排列来处理。
调查索赔:
不用说,这位同事对C有点偏见,但他比我更有经验,可能知道他在说什么。我是语言不可知论者。但这立即让我想到了。怎么能不能用C++进行进程间通信呢?我用谷歌搜索,第一次点击总是来自 stackoverflow,就像这样:
我查看了此处列出的不同 IPC 方法。 https://en.wikipedia.org/wiki/Inter-process_communication#Approaches
我的意思是,我跟进了列表中的每个方法,如管道或共享内存等,每个人都不断指出的唯一警告是,不能像这样传递指针(废话!当然)和一些问题同步可能会蔓延 - je nachdem。
但是我找不到任何可以反驳或证实他的“主张”的东西。(当然,我可以在剩下的时间里继续挖掘。:P)
问题:
他的三个主张真的如此还是只是FUD?考虑到这一点,我想要传递的那些对象中的所有内容也只是 POD 变量和一些 STL 容器,如std::vectorandstd::pair和它们的值(没有指针或任何东西),以及这些变量的 getter。除了虚拟析构函数之外没有任何虚拟函数,它存在是因为我从一个基本消息类继承了所有消息,因为当时我在想可能有一些通用的基本功能。(我现在可以很容易地摆脱这个基类,因为到目前为止还没有真正常见的东西!谢天谢地,出于某种原因,我将消息的解析和格式化保留在一个单独的类中。运气还是远见?:D)
它实际上也让我想知道,编译器如何知道结构何时是 C 样式结构,因为我们在整个项目中都使用 g++ 编译器?是否使用了“virtual”关键字?
我不是在为我的情况寻求解决方案。我可以将这些对象的结果包装到结构中并通过 IPC 传递它们,或者我可以摆脱上面“我的”第 1 点中所述的基类和虚拟析构函数。
不需要 Boost 或任何 C++11 的东西或任何处理此问题的库。在这方面的任何建议都与手头的问题无关。
(ps现在我发布并重新阅读了我发布的内容,我想将任何阅读此内容的读者脑海中可能出现的想法扼杀在萌芽中,那个......我是为了我的知识而问这个问题,而不是与那位同事争论。怀疑是好的,但如果我们都假设其他人的意图是好的,那么对社区会很好。:))
唯一需要注意的是,每个人都不断指出,不能像这样传递指针(废话!当然)
指针值(以及其他对内存和资源的引用)在进程间确实毫无意义。这显然是虚拟内存的结果。
另一个警告是,虽然 C 标准为结构指定了精确的(特定于平台的)内存布局,但 C++ 标准通常不保证类的特定内存布局。例如,一个进程在成员之间的填充量上不一定与另一个进程一致——即使在同一系统内。C++ 仅保证标准布局类型的内存布局 - 这种保证布局与 C 结构匹配。
...和一些 STL 容器,如 std::vector ...(没有指针或任何东西)
除了在std::array内部使用指针之外的所有标准容器。它们必须这样做,因为它们的大小是动态的,因此必须动态分配数据结构。此外,这些都不是标准布局类。此外,一个标准库实现的类定义不能保证与另一个实现匹配,两个进程可以使用不同的标准库——这在 Linux 上并不罕见,其中一些进程可能使用 libstdc++(来自 GNU)而其他进程可能使用 libc++(来自铿锵)。
除了虚析构函数之外没有虚函数
换句话说:至少有一个虚函数(析构函数),因此有一个指向vtable的指针。并且也没有保证的内存布局,因为具有虚函数的类从来都不是标准的布局类。
所以要回答这些问题:
大多数情况下没有 FUD,尽管有些说法在技术上有点不准确:
C++ 标准定义了类是标准布局的确切条件。所有 C 结构定义都是 C++ 中的标准布局类。编译器知道这些规则。
这不是一个问题。
结论:你可以将 C++ 用于 IPC,但您仅限于该界面中的标准布局类。这将您排除在许多 C++ 功能之外,例如虚函数、访问说明符等。但不是全部:例如,您仍然可以拥有成员函数。
但是请注意,使用 C++ 功能可能会导致进程间接口仅适用于 C++。许多语言可以与 C 交互,但几乎没有任何语言可以与 C++ 交互。
此外:如果您的“进程间”通信超出了系统的边界 - 跨网络 - 即使是 C 结构或标准布局类也不是一个好的表示。在这种情况下,您需要序列化。