天天看點

c99變長數組,C99變長數組大小最大和sizeof功能

c99變長數組,C99變長數組大小最大和sizeof功能

I am experimenting with the use of Variable Length Arrays (VLAs) in my C code and trying to iron out my understanding of what they should and shouldn't do.

I have the following snippet from my function:

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 is a data structure containing, amongst other things, packet_size, which is of type size_t

the char array buf is to be used to store the contents of a usb bulk transfer packet

I'm trying to instantiate it here as an automatic variable using the C99 VLA approach. I'm then trying to ensure its contents are all zeros.

I'm having a few issues.

Firstly, if pdw_io->packet_size is set to 8 (quite small), then buf is set to a reasonable looking value, i.e. debugging with gdb i can inspect it as follows:

(gdb) p buf

$27 = 0xbffe5be8 "\270",

If pdw_io->packet_size is set to 12008 (fair bit larger), then I get the following which doesn't look so good:

(gdb) p buf

$29 = 0xbffe2d08 ""

Is 12008 chars too large for a VLA? Or perhaps that gdb output is not something to worry about, it just looks a bit like it hasn't allocated anything to me?

Also when inspecting the size of buf I get the following in both cases:

(gdb) p sizeof(buf)

$30 = 0

which I would have expected to be 8 in the 1st instance and 12008 in the 2nd

Am I wrong in thinking it should be possible to use the sizeof function in this way with a VLA?

My problem is that the subsequent usb bulk transfer is failing and I want to try and rule out the fact it may have something to do with my use of VLAs, which are a bit of a new area for me..

UPDATE

Wrote the following minimal, complete and hopefully verifiable program to try and confirm my observations:

#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;

}

now if I break on the printf statement with gdb and run p sizeof buf I get 0 but printf outputs 12008.

gdb version is:

(gdb) show version

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

解決方案

The problem you're running into is a bug (or perhaps more accurately a missing feature) in gdb. gdb does not correctly handle the sizeof operator applied to a VLA (variable-length array).

This message from a gdb mailing list indicates that support for sizeof on VLAs has been implemented in gdb, but only relatively recently. Apparently it isn't in the version you and I are both using (gdb 7.7.1). Without that fix, it incorrectly prints the size of a VLA as 0. Your code itself should behave correctly; it's just gdb that isn't handling it properly.

There's nothing particularly wrong with your code, as long as (a) it's compiled with a compiler that supports VLAs, and (b) the size of the array is positive and not too large. (VLAs are not supported in C90, except perhaps as an extension, were introduced as a standard feature in C99, and were made optional in C11.)

A possible workaround is to modify your program to save the value of sizeof vla to a variable that you can then print from gdb.

Another problem with gdb is that printing the VLA object itself behaves differently than printing a fixed-size array object. It apparently treats a VLA as a pointer to its first element rather than as an array object.

Here's a gdb transcript that illustrates the problem:

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 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

Is 12008 chars too large for a VLA?

Probably not. For most implementations, a VLA can be just as large as a fixed-size array. There's no real difference (in terms of memory allocation) between:

{

int size = 12008;

char buf[size];

}

and

{

int buf[12008];

}

Many systems limit the amount of memory you can allocate on the stack, but a 12008-byte array isn't likely to push those limits.

Still, if you're going to be allocating large arrays, it's probably better to do so via malloc() (which means you'll need to explicitly call free() for each allocated object).