相关疑难解决方法(0)

使用可变长度数组有任何开销吗?

使用可变长度数组有一些开销吗?可以在运行时通过命令行参数传递数组的大小吗?与自动和动态分配数组相比,为什么会引入它?

c arrays variable-length-array

46
推荐指数
2
解决办法
2万
查看次数

STD 中的动态内存分配

经常使用微控制器和 C++,知道我不执行动态内存分配对我来说很重要。但是,我想充分利用 STD 库。确定 STD 中的函数/类是否使用动态内存分配的最佳策略是什么?

到目前为止,我想出了这些选项:

  1. 阅读并理解 STD 代码。这当然是可能的,但老实说,这不是最容易阅读的代码,而且代码很多。
  2. 阅读代码的一种变体可能是让脚本搜索内存分配并突出显示这些部分以使其更易于阅读。这仍然需要弄清楚在哪里使用分配内存的函数,等等。
  3. 只是测试我想使用的内容并使用调试器观察内存。到目前为止,我一直在使用这种方法,但这是一种反应式方法。我想在设计代码时事先知道我可以从 STD 中使用什么。还有什么可以说在某些(边缘)情况下分配了内存。这些可能不会出现在这个有限的测试中。
  4. 最后,可以做的是定期扫描生成的汇编代码以进行内存分配。我怀疑这可以编写脚本并包含在工具链中,但这又是一种反应式方法。

如果您看到任何其他选项或有做类似事情的经验,请告诉我。

ps 目前我主要使用 ARM Cortex-Mx 芯片使用 GCC 进行编译。

c++ embedded arm std cortex-m

13
推荐指数
1
解决办法
459
查看次数

无论如何,VLA有什么意义?

我理解变量长度数组是什么以及它们是如何实现的.这个问题是关于他们存在的原因.

我们知道VLA只允许在功能块(或原型)中使用,并且它们基本上不能在堆栈上的任何地方(假设正常实现):C11,6.7.6.2-2:

如果标识符被声明为具有可变修改类型,则它应该是普通标识符(如6.2.3中所定义),没有链接,并且具有块范围或函数原型范围.如果标识符被声明为具有静态或线程存储持续时间的对象,则它不应具有可变长度数组类型.

我们举一个小例子:

void f(int n)
{
    int array[n];
    /* etc */
}
Run Code Online (Sandbox Code Playgroud)

有两种情况需要注意:

  • n <= 0:f必须防范这一点,否则行为是不明确的:C11,6.7.6.2-5(强调我的):

    如果size是一个不是整数常量表达式的表达式:如果它出现在函数原型范围的声明中,则将其视为替换为*; 否则, 每次评估它时,其值应大于零.可变长度数组类型的每个实例的大小在其生命周期中不会改变.如果size表达式是运算sizeof符操作数的一部分,并且更改size表达式的值不会影响运算符的结果,则无法指定是否计算size表达式.

  • n > stack_space_left / element_size:没有标准的方法可以找到剩余多少堆栈空间(因为只要涉及标准就没有堆栈这样的东西).所以这个测试是不可能的.只有明智的解决方案才是拥有预定义的最大可能大小n,例如N,确保不会发生堆栈溢出.

换句话说,程序员必须确保0 < n <= N一些N选择.但是,程序应该n == N仍然可以工作,所以人们也可以声明数组的大小N是常量而不是可变长度n.

我知道引入了VLA以替换alloca(在本回答中也提到过),但实际上它们是相同的(在堆栈上分配可变大小的内存).

所以问题是为什么allocaVLA存在并且因此VLA存在以及它们为什么不被弃用?在我看来,使用VLA的唯一安全方法是使用有限大小,在这种情况下,采用具有最大大小的正常阵列始终是可行的解决方案.

c variable-length-array

12
推荐指数
4
解决办法
8382
查看次数

标签 统计

c ×2

variable-length-array ×2

arm ×1

arrays ×1

c++ ×1

cortex-m ×1

embedded ×1

std ×1