繁体   English   中英

C99可变长度数组的最大大小和sizeof函数

[英]C99 Variable Length Array Max sizes and sizeof 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", <incomplete sequence \370\267>

如果将pdw_io->packet_size设置为12008( pdw_io->packet_size大一点),那么我得到的结果看起来不太好:

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

12008字符对于VLA是否太大? 或者,也许不用担心gdb输出,它看起来好像还没有为我分配任何东西吗?

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

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

我本来希望一开始是8,而第二次是12008

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

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

UPDATE

编写了以下最小,完整和可验证的程序,以尝试确认我的意见:

#include <stdio.h>

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的错误(或更准确地说是缺少的功能)。 gdb无法正确处理应用于VLA(可变长度数组)的sizeof运算符。

来自gdb邮件列表的此消息表明,已在gdb实现了对VLA上sizeof支持,但只是最近才实现的。 显然,您和我都没有使用的版本(gdb 7.7.1)。 如果没有该修补程序,它会将VLA的大小错误地打印为0。 只是gdb无法正确处理它。

只要(a)使用支持VLA的编译器进行编译,并且(b)数组的大小为正数且不会太大,则您的代码就没有什么特别的问题。 (在C90中不支持VLA,除非作为扩展,在C99中作为标准功能引入了VLA,并在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 <stdio.h>
2       #include <string.h>
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 c.c, line 10.
(gdb) run
Starting program: /home/kst/c 

Breakpoint 1, main () at c.c: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

12008字符对于VLA是否太大?

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

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

{
    int buf[12008];
}

许多系统都会限制您可以在堆栈上分配的内存量,但是12008字节的数组不太可能达到这些限制。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM