Local variable length array - c

during some code refactor in C++ i meet following local variable length arrays
void some_function(uint8_t length, uint8_t id, uint8_t * bytes)) {
uint8_t string[length + 8];
//some transformation on string [1-8] elements
do_something(string);
}
I am not familiar with C99 but using Variable-length array size [x+y] look like this will be placed in heap. Also I debug this function to make sure that this "string" variable is placed on heap and it is.
In C local variables can't be fixed size, so they are not needed to clean up after using them. But here we have fixed size array without memory allocation, so is no need to clean up after this variable, but how GCC compiler manage this memory?
Or maybe on other way to clarifying what I am considering here: length variable is coming from external IO so in my opinion there can be security issue (for example when length will be INTEGER_MAX value), besides check the size of length what other actions can be taken to have secure code here? Or maybe it is already secure?

What you see in this code is a C99 Variable Length Array. A similar proposal almost made it to C++14, but didn't. So this code is not valid STANDARD C++, but your compiler may support it. AFAIK, C99 VLAs store their memory on the stack.

See this question and this one. It's a GCC extension:
Variable-length automatic arrays are allowed in ISO C99, and as an extension GCC accepts them in C90 mode and in C++. These arrays are declared like any other automatic arrays, but with a length that is not a constant expression. The storage is allocated at the point of declaration and deallocated when the block scope containing the declaration exits.

Related

setting the size of array

i am solving a problem. In my code i have two arrays
array[];
array2[];
i am inputing 2 numbers through scanf , and i want the size of arrays to be the count of number 1 and 2 e.g
int x;
int y;
scanf(" %d %d\n",&x,&y);
int indexX[x*y];
int indexY[x*y];
This does not work.
Being new to C im quite lost how to implement it , is the only way dynamicly allocate memory? If no , how can i achieve wanted result ? Or how could i dynamicly alocate the memory for it?
my code throws error
warning: ISO C++ forbids variable length array ‘indexX’ [-Wvla]
warning: ISO C++ forbids variable length array ‘indexY’ [-Wvla]
According to your error messages, you compile with a C++ compiler. Do not! C is not C++ and C++ is not C with classes. They are different languages. As the messages state, C++ does not provide VLAs (see below).
Use a standard-compliant C compiler, or at least a C99 compiler. Variable length arrays (VLAs) were added with the C99 release of the standard as a mandatory feature. C11 relaxed this by making it optional, but most (if not all) compilers which support C99 also implement it in C11 mode.
before defining the array, you should verify scanf really set these two variables by checking the result of scanf. Otherwise you use uninitialised variables, which is undefined behaviour and may (likely - will) result in strange behaviour - at best.
Additinally you can also initialise the variables before scanf to 1 (a VLA of size 0 is also undefined behaviour). This way you can check later and are still safe with the VLA definition.
Warning: Most, if not all modern implementations place VLAs on the stack. The size of the stack is normally limited to some 100 bytes (embedded systems) up to some MiB (standard OS like Windows, OS-X, Linux). There is no check if the VLA fits onto the stack, so you should not allocate too large arrays. If you are not sure, better use dynamically allocated memory (malloc& friends).

Assigning a dynamic array using declaration for static array in C?

So for example,
int aaa(unsigned int par1, unsigned int par2){
int array[par1*par2];
return 0;
}
I tried compiling the code that contains this, and it compiled well and had no run-time issue - the array was properly created.
But I know that this is basically declaring a dynamic array in static array declaration fashion. What may go wrong with this declaration? Will there be a compiler issue in a different compiler?
This is correct as per the 1999 C standard. The 2011 standard changed it to be an optional feature, which in practice means that all C11 compilers will support it except for MSVC.
Before 1999 some compilers offered this as a non-standard extension.
Here is a link to StackOverflow search for other questions on this topic.
But I know that this is basically declaring a dynamic array in static array declaration fashion.
This is called VLA (Variable-Length Array). This array is not static - it is placed in automatic memory (also known as "the stack").
What may go wrong with this declaration?
It may overflow the stack when the size of the array exceeds a certain limit specific to your system.
Will there be a compiler issue in a different compiler?
This is a C99 feature, so compiler that do not support C99 may fail to compile this code.
I believe this is a C99-only feature. It's called VLA (variable-length arrays).
The C++0x does't support VLA:
https://groups.google.com/forum/#!topic/comp.std.c++/K_4lgA1JYeg
But some compilers might not be strictly compliant with the standard.

Dynamic array declaration in C

Following piece of code compiles in gcc. But it is not correct way of writing as it surpasses the use of malloc function. What is the problem in this code?
#include<stdio.h>
main()
{
int n;
scanf("%d",&n);
int a[n];
}
your code is legal ISO C99 code. It's not C89 ANSI compliant: if you are stuck with compatibility rules, because of old compilers or company policies, you need to use malloc().
More importantly, in C99, using your definition, the array is allocated on stack, that is usually a limited resource, while with malloc() it's allocated in the heap.
Your array is a variable length array (VLA). This is an advanced feature of C, introduced in the C99 version of the standard.
The problem with VLAs is that they can easily overflow the stack. Unless you have a specific reason to use a VLA, use dynamic memory with malloc and avoid the risk of stack overflow.
Your main declaration is wrong. It should be
int main(void)
"...it is not correct way of writing as it surpasses the use of malloc function..." - what is that supposed to mean? According to the rules of modern C language, the only problem with your code is the missing int in the declaration of main. I.e. it has nothing to do with any malloc.
It can be said that your code is self-contradictory in a sense that it uses a perfectly valid C99 feature - variable length array int a[n] - but at the same time relies on an obsolete feature of C89/90 - implied int in the declaration of main, which is no longer supported by C99.
You need to decide which version of C language you are trying to use - C89/90 or C99. Once you make that decision, we'll be able to discuss the correctness of your code.

Why is variable length array forbidden: "C90 forbids variable length array"?

I know that I'm not supposed to do this in C90, and it's a rather basic stuff.
char name[strlen(s)];
ArrayLength.c:11: warning: ISO C90 forbids variable length array ‘name’
Did they want me to specifically use malloc? I'm just curios here about the logic behind it.
It's forbidden because C90 doesn't support variable-length arrays (VLAs). It's really as simple as that.
Your options are:
Declare a fixed-length array that can cope with the maximum string length you want to work with.
Dynamically-allocate the array (using malloc).
Work with a compiler that offers VLAs a non-standard language extension, e.g. GCC. (I don't recommend this, because it means you'll end up writing non-portable code.)
Use C99 instead, where VLAs are supported. Note that VLAs are allocated on the stack, which can cause all sorts of issues if you run out of stack space (unlike with malloc, there's no concept of being able to check that the allocation was successful).
[Note: If you're allocating an array in order to make a copy of s, you'll need to use strlen(s)+1 as the size (remember the null terminator).]
It's not that "they" don't want you to do it, it's simply not part of the language (or rather, wasn't prior to 1999). The standard workaround is to use malloc or alloca. (alloca is essentially identical to variable length array allocation, but is not a standard function, so it may not be available on all systems of interest. Also, some people have strong objections to it's use, but they tend to object strong to variable-length arrays for the same reasons.)
This warning points to the usage of a GNU gcc extension is a serious portablity problem.
The code is illegal, because the value of strlen(s) is not known at compile time. GNU gcc provides an extension for automatic arrays that allocate based on run time values; but relying on these makes the code out of compliance with the standard.
If the value of strlen(s) isn't known until run-time then one can bring the code into compliance by either converting to performing the allocation/deallocation explicitly on conventions arrays, or by using STL containers.(e.g. std::vector).
It's a matter of the language having restrictions for the presumed convenience of the
compiler and its intended runtime environment.

The const modifier in C

I'm quite often confused when coming back to C by the inability to create an array using the following initialisation pattern...
const int SOME_ARRAY_SIZE = 6;
const int myArray[SOME_ARRAY_SIZE];
My understanding of the problem is that the const operator does not guarantee const-ness but rather merely asserts that the value pointed to by SOME_ARRAY_SIZE will not change at runtime. But why can the compiler not assume that the value is constant at compile time? It says 6 right there in the source code...
I think I'm missing something core in my fundamental understanding of C. Somebody help me out here. :)
[UPDATE]After reading a bit more around C99 and variable length arrays I think I understand this a bit better. What I was trying to create was a variable length array - const does not create a compile time constant but rather a runtime constant. Therfore I was initialising a variable length array, which is only valid in C99 at a function/block scope. A variable length array at the file scope is impossible as the compiler cannot assign a fixed memory address to an unbounded array.[/UPDATE]
Well, in C++ the semantics are a bit different. In C++ your code would work fine. You must distinguish between 2 things, const and constant expression. Const means simply, as you described, that the value is read-only. constant expression, on the other hand, means the value is known compile time and is a compile-time constant. The semantics of const in C are always of the first type. The only constant expressions in C are literals, that's why #define is used for such kind of things.
In C++ however, any const object initialized with a constant expression is in itself a constant expression.
I don't know exactly WHY this is so in C, it's just the way it is
The problem is that the language syntax demands a integer value between the [ ]. SOME_ARRAY_SIZE is still a variable (even if you told the compiler nobody is allowed to vary it!)
The const keyword is basically a read-only indication. It does not, really, indicate the underlying value will not change, even though that is the case in your example.
When it comes to pointers, this is more clear:
void foo(int const * p)
{
if (*p == 100)
{
bar();
/* Here, the compiler can not assume that *p is 100 */
}
}
In this case, a compiler should not accept the code in your example, as it requires the array size to be constant. If it would accept it, the user could later run into trouble when porting the code a more strict compiler.
You can do this in C99, and some compilers prior to C99 also had support for this as an extension to C89 (e.g. gcc). If you're stuck with an old compiler that doesn't have C99 support though (e.g. MSVC) then you'll have to do it the old skool way and use a #define for the array size.
Note that that above comments apply only to such declarations at local scope (i.e. automatic variables). C99 still doesn't allow such declarations at global scope.
i just did a very quick test with my Xcode and Objective C file I currently had open on my machine and put this in the .m file:
const int arrs = 6;
const int arr[arrs];
This compiles without any issues.

Resources