6

我遇到了一个奇怪的问题,我已经能够找到一些问题,但我仍然看不到原因。也许这里有人可以提供一些启示?

我正在使用 PPCgnu604 工具链在 C++ 中开发的 VxWorks 5.5 之上的 PowerPC 处理器上运行。

我有这样的课:

class MyClass
{
  public:
    void run( void );
  private:
    CommandMesssageClass command;
    StatusMessageClass status;
};

当我的应用程序启动时,它将动态分配 MyClass 的一个实例并生成一个指向其“运行”函数的线程。本质上,它只是坐在那里轮询命令,并在收到后返回一个状态。

请注意,这是该课程的精简版。为简洁起见,还有许多其他方法和变量被省略。

我看到的问题是,当命令和状态消息都被定义为私有类成员时,尽管事实上不应该有动态内存分配,但我将在内存中的可用字节中得到改变。这很重要,因为这发生在需要确定性和速率安全的程序中。

如果我将一个或两个消息声明移动到运行函数中,它可以正常工作而无需额外分配!

在我对 C++ 声明和内存分配的理解中,我一定遗漏了一些基本的东西。我的理解是,我动态实例化的类实例在创建时将完全分配在堆上(包括所有成员变量)。我在这里看到的不同之处在于,将消息声明移动到 run 函数会将它们放在堆栈上。在这种情况下,堆的大小足以容纳整个类的大小。为什么在使用特定部分之前似乎没有分配足够的内存?

消息类没有自己的动态分配。(如果他们这样做了,我希望移动声明不会改变这种情况下的行为,我仍然会看到堆大小的变化。)

为了监控内存分配,我使用了以下 VxWorks memLib(或 memPartLib)调用:

memPartInfoGet( memSysPartId, &partitionStatus );
...
bytesFree = partitionStatus.numBytesFree;

编辑:

澄清一下,MyClass 对象在初始化例程中被实例化和初始化,然后代码进入速率安全处理。在此期间,在通过串行线路接收命令消息(与命令或状态消息对象的第一次交互)时,分配额外的内存(或者更确切地说,空闲字节数减少)。这很糟糕,因为动态内存分配不是确定性的。

正如我所描述的,我已经能够通过移动类变量来解决这个问题。

4

1 回答 1

2

在我对 C++ 声明和内存分配的理解中,我一定遗漏了一些基本的东西。

我不这么认为。你所说的你所期望的一切都是正确的——游戏程序员一直都严重依赖这种行为。:-)

为什么在使用特定部分之前似乎没有分配足够的内存?

为简洁起见,您省略了课程的内容。我有一些调试类似问题的经验,我最好的猜测是,在某个地方,库函数实际上是在进行你不知道的运行时分配。

换句话说,两种情况下都存在运行时分配,但是 MyClass 的两种不同大小意味着 malloc 池的填充方式不同。您可以通过将对象移动到 run() 中的堆栈来证明这一点,但将 MyClass 填充到相同的大小。如果您仍然看到空闲内存下降,那么它与这些对象是在堆上还是在堆栈上无关……这是由于 MyClass 的大小而发生的次要影响。

请记住,malloc 很笨重——大多数实现不会为每次调用 malloc 进行一对一的分配。相反,它过度分配并将内存保留在池中,并在必要时增加这些池。

我不熟悉您的工具链,但嵌入式系统上意外小分配的典型嫌疑人包括 ctype 函数(语言环境)和日期/时间函数(时区)。

于 2010-08-18T07:41:00.313 回答