C99可变长度arrays最大尺寸和尺寸function

我正在尝试在我的C代码中使用可变长度数组(VLA),并试图理解我们应该和不应该做什么。

我的函数有以下代码片段:

void get_pdw_frame_usb(pdws_t *pdw_frame, pdw_io_t *pdw_io) { ... unsigned char buf[pdw_io->packet_size]; unsigned char *pdw_buf; memset(buf, '\0', sizeof(buf)); 

pdw_io是一个数据结构,其中包含packet_size ,其类型为size_t

char数组buf用于存储usb批量传输数据包的内容

我试图在这里使用C99 VLA方法将其实例化为自动变量。 我正在努力确保其内容全部为零。

我有一些问题。

首先,如果pdw_io->packet_size设置为8(非常小),则将buf设置为合理的值,即使用gdb进行调试,我可以按如下方式检查:

 (gdb) p buf $27 = 0xbffe5be8 "\270",  

如果pdw_io->packet_size设置为12008(相当大),那么我得到以下看起来不太好的:

 (gdb) p buf $29 = 0xbffe2d08 "" 

对于VLA,12008个字符是否太大? 或者也许gdb输出不值得担心,它看起来有点像它没有分配任何东西给我?

另外,在检查buf的大小时,我在以下两种情况下都会得到以下结果:

 (gdb) p sizeof(buf) $30 = 0 

我原本预计在第一个实例中是8个,在第二个实例中是12008个

我认为应该可以通过VLA以这种方式使用sizeof函数,这是错误的吗?

我的问题是随后的usb批量传输失败了,我想尝试排除它可能与我使用VLA有关的事实,这对我来说是一个新的领域。

UPDATE

写下以下最小,完整且有希望validation的程序,以尝试确认我的观察结果:

 #include  void test_vla(size_t n) { unsigned char buf[n]; printf("sizeof buf = %zu\n", sizeof buf); } int main() { test_vla(12008); return 0; } 

现在,如果我使用gdb打破printf语句并运行p sizeof buf我得到0但printf输出12008。

gdb版本是:

 (gdb) show version GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1 

您遇到的问题是gdb的错误(或者可能更准确地说是缺少的function)。 gdb无法正确处理应用于VLA(可变长度数组)的sizeof运算符。

来自gdb邮件列表的此消息表明,已在gdb实现了对VLA上sizeof支持,但仅在最近才实现。 显然它不在你和我都使用的版本中(gdb 7.7.1)。 如果没有这个修复,它会错误地将VLA的大小打印为0.您的代码本身应该正常运行; 它只是gdb没有正确处理它。

你的代码没有什么特别的错误,只要(a)它是用支持VLA的编译器编译的,并且(b)数组的大小是正的而不是太大。 (C90中不支持VLA,但可能作为扩展,在C99中作为标准function引入,并且在C11中是可选的。)

一种可能的解决方法是修改程序以将sizeof vla的值保存到可以从gdb打印的变量。

gdb另一个问题是打印VLA对象本身的行为与打印固定大小的数组对象不同。 它显然将VLA视为指向其第一个元素而不是数组对象的指针。

这是一个说明问题的gdb脚本:

 GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1 [SNIP] (gdb) list 1 #include  2 #include  3 int main(void) { 4 int len = 6; 5 char vla[len]; 6 const size_t vla_size = sizeof vla; 7 char arr[6]; 8 strcpy(vla, "hello"); 9 strcpy(arr, "world"); 10 } (gdb) break 10 Breakpoint 1 at 0x400600: file cc, line 10. (gdb) run Starting program: /home/kst/c Breakpoint 1, main () at cc:10 10 } (gdb) print sizeof vla $1 = 0 (gdb) print vla_size $2 = 6 (gdb) print sizeof arr $3 = 6 (gdb) print vla $4 = 0x7fffffffdc10 "hello" (gdb) print arr $5 = "world" (gdb) print arr+0 $6 = 0x7fffffffdc40 "world" (gdb) continue Continuing. [Inferior 1 (process 28430) exited normally] (gdb) quit 

对于VLA,12008个字符是否太大?

可能不是。 对于大多数实现,VLA可以与固定大小的arrays一样大。 两者之间没有真正的区别(就内存分配而言):

 { int size = 12008; char buf[size]; } 

 { int buf[12008]; } 

许多系统限制了您可以在堆栈上分配的内存量,但是12008字节的arrays不太可能推动这些限制。

但是,如果您要分配大型数组,最好通过malloc() (这意味着您需要为每个已分配的对象显式调用free() )。