可变长度阵列性能影响(C / C ++)

时间:2013-09-27 03:38:35

标签: c++ c arrays

我正在写一个相当简单的函数,它将数组发送到文件描述符。但是,为了发送数据,我需要附加一个字节的头。

以下是我正在做的简化版本,似乎有效:

void SendData(uint8_t* buffer, size_t length) {
  uint8_t buffer_to_send[length + 1];
  buffer_to_send[0] = MY_SPECIAL_BYTE;
  memcpy(buffer_to_send + 1, buffer, length);
  // more code to send the buffer_to_send goes here...
}

就像我说的那样,代码似乎工作正常,但是,我最近养成了使用Google C ++风格指南的习惯,因为我当前的项目没有设置样式指南(我实际上是唯一的软件)工程师在我的项目上,我想使用在工业中使用的东西)。我运行了Google的cpplint.py,它抓住了我创建buffer_to_send的行,并抛出了一些关于不使用可变长度数组的注释。具体来说,这就是Google的C ++风格指南对变长数组的说法......

http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Variable-Length_Arrays_and_alloca__

基于他们的评论,似乎我可能找到了我的代码中看似随机崩溃的根本原因(这种情况很少发生,但仍然令人讨厌)。但是,我对如何解决它感到有些不知所措。

以下是我提出的解决方案:

  1. 使buffer_to_send基本上是一个恒定长度的固定长度数组。我能想到的问题是我必须使缓冲区与我想要发送的理论上最大的缓冲区一样大。在一般情况下,缓冲区要小得多,每次调用函数时我都会浪费大约0.5KB。请注意,程序必须在嵌入式系统上运行,虽然我不一定要计算每个字节,但我想尽可能少地使用内存。

  2. 使用new和delete或malloc / free动态分配缓冲区。这里的问题是频繁调用该函数,并且在不断询问操作系统内存然后释放它时会有一些开销。

  3. 使用两次连续的write()调用,以便将数据传递给文件描述符。也就是说,第一次写入只传递一个字节,而下一次写入将发送剩余的缓冲区。虽然看起来很简单,但我需要对代码进行更多的研究(请注意,我从之前离开我工作的公司的工程师处获得了此代码),以保证两次连续写入以原子方式发生。此外,如果这需要锁定,那么它实际上变得更复杂,并且比情况#2具有更多的性能影响。

  4. 请注意,我无法使buffer_to_send成为成员变量或将其作用于函数外部,因为在任何给定时间(可能)都会从各种线程对函数进行多次调用。

    请让我知道您的意见以及我的首选方法。谢谢你的时间。

2 个答案:

答案 0 :(得分:3)

您可以使用writev()将选项3中的两个连续调用write()折叠成一个调用。

http://pubs.opengroup.org/onlinepubs/009696799/functions/writev.html

答案 1 :(得分:0)

我会选择选项1.如果您知道数据的最大长度,则使用固定大小的数组在堆栈上分配那么多空间(加上一个字节)。这并不比你所显示的可变长度数组差,因为你必须总是有足够的空间留在堆栈上,否则你将无法处理你的最大长度(最糟糕的是,你的代码会在较大的缓冲区大小上随机崩溃)。在调用此函数时,没有其他任何东西可以使用堆栈上的更多空间,因此分配固定大小的数组是安全的。