【问题标题】:Named Pipe strategies with dynamic memory?具有动态内存的命名管道策略?
【发布时间】:2009-09-08 02:28:24
【问题描述】:

好吧,所以我有一个需要 IPC 的应用程序...我认为命名管道是可行的方法,因为它们非常易于使用。

无论如何,我有一个关于如何使用命名管道处理动态内存的问题。

假设我有这样的课程:

class MyTestClass {
public:
    MyTestClass() { _data = new int(4); }

    int GetData() { return *_data; }
    int GetData2() { return _data2; }

private:
    int* _data;
    int _data2;
};

现在,当我创建一个充满MyTestClass 对象的缓冲区然后通过管道发送它们时,我显然会在目标进程中丢失_data 并获得垃圾。我应该使用一些策略吗?我可以在简单的情况下使用值类型,但对于许多复杂的类,我需要使用某种动态内存,而且我喜欢指针。

或者,我应该只考虑使用共享内存吗?谢谢

【问题讨论】:

  • 我认为你应该删除 _data2 之类的。它不完整(已初始化),我认为没有它你的问题很清楚。
  • 由于您的构造函数分配内存,您需要一个析构函数来释放该内存,不是吗?
  • 是的,我确实需要发布它,对于糟糕的形式,我很抱歉......我只是想明白这一点

标签: c++ windows linux memory-management named-pipes


【解决方案1】:

命名管道和共享内存都有类似的问题:您需要将结构的内容序列化到发送端,并从接收端反序列化结构。

无论您使用的是命名管道还是共享内存,序列化过程本质上是相同的。对于嵌入式指针(如 _data 和 _data2),您需要以一致的方式序列化指针的内容。

您可以使用许多序列化策略,具体取决于您的结构在内存中的布局方式以及 IPC 的效率。或者您可以使用 DCE RPC 并让 RPC 编组代码为您处理复杂性。

【讨论】:

  • 感谢您的回复...关于我可以使用的协议或我可以使用的序列化策略的任何提示?谢谢
  • 如果您正在寻找序列化策略,到目前为止最常见的情况是文件存储。您将如何将您的课程写入文件并稍后读回?如果您将 IPC 通道包装为 std::streambuf,您可能可以节省大量工作;这样您就可以共享和重用大量代码。
  • MSalters 直接从我嘴里说出来的话。他的建议是正确的。
【解决方案2】:

要通过命名管道发送数据,您必须在发送端序列化(或编组)数据,并在接收端对其进行反序列化(或解组)。

这听起来很可疑,好像您只是在数据结构中写入字节的副本。这一点都不好。您没有复制分配的数据(它没有存储在数据结构的第一个和最后一个字节之间,而是完全存储在其他地方)并且您正在将指针(_data)从一台机器(或进程)复制到另一台机器,而本地进程中的内存地址在其他进程中没有保证意义。

为自己定义一个有线协议(如果不相关,请查看 ASN.1 - 不,再想一想,不要那么极端),它定义了通过有线传输的数据布局。然后实现发送器和接收器(或序列化器和反序列化器)功能。或者找到其他人的代码已经这样做了。

还要记住处理字节序 - 您必须定义字节通过命名管道发送的顺序。

例如,您可以定义发送的消息由一个 4 字节无符号整数组成,按网络字节顺序定义后面有多少个结构,每个结构可以是数组的 4 个有符号 4 字节整数的序列,后跟_data2 的单个有符号 4 字节整数(也以网络字节顺序发送)。

请注意,选择命名管道作为 IPC 机制在很大程度上是无关紧要的;除非您使用共享内存(本来就在同一台机器上),否则必须处理字节序,即使使用共享内存,您也需要处理序列化。

【讨论】:

  • 谢谢...这就是我的想法...我对 IPC 的东西有点陌生。现在我只是通过哈哈发送原始字节......我想看看这些 IPC 机制的限制是什么。你 100% 正确地认为字节不在数据结构中……这正是我试图解决的问题。
猜你喜欢
  • 2020-02-21
  • 1970-01-01
  • 2012-03-28
  • 2016-09-24
  • 1970-01-01
  • 2022-07-24
  • 1970-01-01
  • 1970-01-01
  • 2022-01-03
相关资源
最近更新 更多