How use local array in function - ANSI C? - arrays

I want to add something to the end of the array passed to the function.
Which is better, declaring a new larger array or using alloc ()?
1.
void array_append(int *block, size_t size)
{
int new_block[size + 2];
memcpy(new_block, block, size);
(...append)
}
void array_append(int *block, size_t size)
{
int *new_block = calloc(1, sizeof(int) + 2);
memcpy(new_block, block, size);
(...append)
free(new_block);
}
I am not returning the newly created array anywhere.
I only use new_block inside functions.
Does not modify the original array in the function.
Declaring new_block as static is omitted.
I know how calloc() / malloc() works, I know that this operation has to be validated.
new_block is only meant to live in a function.
I just wonder which solution is better and why ...
regards

You should dynamically allocate an array instead of using a variable length array because in general in the last case the code can be unsafe due to a comparatively big size of the array that can lead to the stack overflow.

I want to add something to the end of the array
But you cannot really. Unless with realloc(). This is how your ...append trick can be done, whatever it means.
If you need a temporary array to work with and then copy into your array (but not at the end!), then all methods for allocation are allowed - it really depends on how often and with which sizes.
If it is called very often with limited sizes, it could be a static array.
There is no easy solution for growing arrays (or for memory management in general). At the extreme you allocate every element individually and link them together: a linked list.
--> avoid reaching the end of your arrays. Define a higher maximum or then implement a linked list.
In certain situations realloc() also makes sense (big changes in size, but not often). Problem is sometimes the whole array has to be memcopied to keep the larger array contiguous: "realloc", not "append". So it is "expensive".
I am not returning the newly created array anywhere.
That is part of the problem. You actually seem to be doing half of what realloc() does: allocate the new space, memcpy() the old contents...and then free the old and return the new array(-pointer) to the caller.
First version can not return the array pointer, because end of function is also end of local auto arrays, VLA or not.

If the append can be done to the existing array (which it can if the caller expects this and the memory of the array has room), you can merely append to the existing array.
Otherwise, you need a new array. In this case, the array must be returned to the caller. You can do this by returning a pointer to its first element or by having the caller pass a pointer to a pointer, and you modify the pointed-to pointer to point to the first element of the new array.
When you provide a new array, you must allocate memory for it with malloc or a similar routine. You should not use an array defined inside your function without static, as the memory for such an array is reserved only until execution of the function ends. When your function returns to the caller, that memory is released for other uses. (Generally, you also should not use an array declared with static, but for reasons involving good design, reducing bugs, and multiple serial or parallel calls to the function.)

Related

How to make static array point to NULL

Is there a possible way to make static array of structs points to NULL since I can't delete arrays and I want to clean the memory?
Suppose we have the following code:
struct_x defaultStructX[6];
struct_x requiredStructX [6];
gettingDefaultX(defaultStructX, 6);
for (uint8_t i = 0; i <6; i++)
{
setStructX(requiredStructX[i].index, requiredStructX[i].icirate, requiredStructX[i].icis, requiredStructX[i].iei);
//error handle case
if (status == STATUS_SUCCESS)
{
writeResponse.writeStatus = status_ok; /*This is another struct not important at this point*/
} else
{
errorHandleQciFlowMeter(defaultStructX, 6);
writeResponse.writeStatus = status_nok;
break;
}
}
/*here I want to write code line to clean the defaultStructX from memory. Is it possible? I have tried *defaultStructX[i]= NULL and ##((void*)defaultQciFlowMeter) = NULL; ## and many other methods but it didn't work*/
Is there a possible way to make static array of stucts points to NULL since I can't delete arrays and I want to clean the memory?
No. Arrays are not pointers, nor are the elements of your particular arrays pointers, either. Pointer values cannot be assigned to either the arrays themselves or to the elements, and in particular, NULL cannot be assigned to them.
You can overwrite the memory occupied by the array with, say,
memset(defaultStructX, 0, sizeof(defaultStructX));
That will replace the data previously stored within,* which might be useful if those data were sensitive. The application would then need to assign new, valid values to the array elements before using them again.
Any way around, however, you cannot free the memory of an object with static storage duration, which is any object declared at file scope, outside all functions, or with the static qualifier inside a function. The entire point of static storage duration is for objects' lifetimes to be the entire duration of the program's run. If you want to be able to release the memory then you should allocate space for your arrays dynamically, or, if it works for your particular application, automatically (as a local variable of a well-chosen function).
* In principle. As #chux noted in comments, it may be the case that the compiler chooses to optimize out such an overwrite, which it might do if it could determine that the zeroed out data were never read. If this is a concern, then the best mitigation would probably be to declare the arrays volatile.
struct_x defaultStructX[6];
struct_x requiredStructX [6];
With the above statements, you have reserved memory for the two arrays of structs. This memory will remain allocated to you during the entire lifetime of your program and cannot be de-allocated until your program exits.
However, what you want to store in this memory is completely under your control. What is your definition of 'cleaning from memory'?
Do you haves some sensitive data that you want to erase from memory? You can always memset them to zero (or any other value) with:
memset(defaultStructX, 0x00, sizeof(defaultStructX));
Do you want to physically de-allocate the memory? If you want to have control over allocation and deallocation of chunks of memory, you should do so with malloc and free.
EDIT: Apparently the memset() solution can be derailed by compiler optimizations.
Here is a useful description of this issue from the SEI CERT C page.
You cannot manually deallocate anything that wasn’t allocated with malloc, calloc, or realloc. If you declared your arrays at file scope (outside of any function) or with the static keyword, then their memory won’t be released until the program terminates. Otherwise, their memory will be released when the function in which they were declared exits.
You can overwrite elements not currently in use with zeros or some other “not a value” value, but you cannot free the memory they occupy.
Arrays are not pointers. Expressions of array type are converted to pointers as necessary, but the array object itself is not a pointer.
Is there a possible way to make static array of structs points to NULL since I can't delete arrays and I want to clean the memory?
No. Arrays do not point. The array could be cleared.
I want to write code line to clean the defaultStructX from memory.
Simply assigned zeros to it.
memset() can get optimized out if the compiler sees the data was not subsequently read.
Alternative: use a loop with a pointer to volatile data to avoid loop from being optimized out.
volatile unsigned char *vp = defaultStructX;
for (size_t i = 0; i<sizeof defaultStructX; i++ {
vp[i] = 0;
}
Hmm... On one hand I love the detailed answer offered by John Bollinger and I believe he gave the correct answer for your use case... however...
There is a way to make the statically allocated array appear to point to NULL.
Obviously you can't assign NULL to an array. However, you can make a statically allocated "Array" seem to point to NULL by hiding it behind a pointer.
It might look like this:
#define STRUCT_X_ARRAY_LENGTH 6
struct_x defaultStructX___[STRUCT_X_ARRAY_LENGTH];
struct_x requiredStructX___[STRUCT_X_ARRAY_LENGTH];
struct_x * defaultStructX = defaultStructX___;
struct_x * requiredStructX = requiredStructX___;
gettingDefaultX(defaultStructX, STRUCT_X_ARRAY_LENGTH);
Now you could set the (no longer) "Array" to NULL using:
defaultStructX = NULL;
requiredStructX = NULL;
You could also reset the state (zero out the memory and reassign the correct memory address) using:
defaultStructX = defaultStructX___;
requiredStructX = requiredStructX___;
memset(defaultStructX___, 0 , sizeof(defaultStructX___));
memset(defaultStructX___, 0 , sizeof(requiredStructX___));
Not that this fits your use case, but it's a good enough technique that others might want to know about it.

C: Array of pointers vs pointer-to-pointer

Do these two pieces of C code achieve the same goal:
char ** p;
p = malloc(sizeof(char*) * 10);
--------------------------------
char * z[10];
It seems like they can be used identically:
p[1] = "Foo";
*(p+2) = "Bar";
---------------------
z[1] = "Foo";
*(z+2) = "Bar";
Is there a difference?
If you just store and retrieve values from the array, or malloc-allocated area, they work the same.
There are differences, though. sizeof and & work differently, you need to explicitly free the malloc-allocated area to release the memory, and you can change its size with realloc.
in terms of use and functionality, there really is no difference except in how you plan to use it.
An example of what I mean is that I could use a double pointer for iterating and dereferencing the whole multidim array.
not to mention that when you malloc, you need a matching free when you're done with it.
Of course, you should only malloc when you think you really need it or you need a massive amount of memory.
Last part I want to say is that with the pointer array, you cannot dereference the individual characters without using the subscript operator []
C memory is split into several types, stacks -for function calls and local variables, and then there is heap -for malloced objects. The stack usually has smaller size than the heap. As a result, if you try to allocate a huge array in stack you might exceed the stack's storage space causing segfault.
In this case when you malloc an array, heap memory is being used .And it will exist until it is explicitly deallocated with free. This is useful in cases where you are using large array size.
Whereas in the first case you are declaring the array in stack,which lives only as long as the function that calls it exists.
Since the array size is small here, both works. But for larger arrays, malloc'ing is recommended to avoid segfault.

Initially mallocate 0 elements to later reallocate and measure size

I have a function that will add a new position to an array by reallocating new memory every time it is called.
The problem is that, for each call I need it to add one position to the array, starting from 1 at first call, but I understand that I have to mallocate before reallocating.
So my question is, can I initially do something like p = malloc(0) and then reallocate for example using p = (int *)realloc(p,sizeof(int)) inside my function? p is declared as int *p.
Maybe with a different syntax?
Of course I could make a condition in my function that would mallocate if memory hasn't been allocated before and reallocate if it has, but I am looking for a better way.
And the second problem I have is... Once reallocated more positions, I want to know the size of the array.
I know that if, for example, I declare an array a[10], the number of elements would be defined by sizeof(a)/sizeof(a[0]), but for some reason that doesn't work with arrays declared as pointers and then reallocated.
Any advice?
You could initialize your pointer to NULL, so that the first time you call realloc(yourPointer, yourSize), it will return the same value as malloc(yourSize).
For your second problem, you could use a struct that contains your pointer and a count member.
struct MyIntVector {
int * ptr;
size_t count;
}
Then you probably will want to define wrapper functions for malloc, realloc, and free (where you could reset ptr to NULL), that takes your struct as one of the parameters, and updates the struct as needed.
If you want to optimize this for pushing 1 element at a time, you could add a allocatedCount member, and only realloc if count == allocatedCount, with a new allocatedCount equals (for example) twice the old allocatedCount.
You should implement this in a MyIntVector_Push(MyIntVector *, int ) function.
You will then have a simplified c version of c++ std::vector<int> (but without automatic deallocation when the object goes out of scope).
As ThreeStarProgrammer57 said just use realloc.
realloc(NULL, nr_of_bytes) is equivalent to malloc(nr_of_bytes)
so
p = realloc(p, your_new_size)
will work just fine the first time if p is initialized to NULL. But be sure to pass the number of bytes you need after resizing, not the additional space that you want, as you have written your question.
As regarding the size, you have to keep track of it. That's the way C was designed.

Remove elements from pointer array

I have a program in which I need to work with pointer arrays. My problem is that I do not know how to delete element i from pointer p (p[i]). I will detail the problem below.
I have the structure:
struct CuttingLine
{
NxU32 linePoints[150];
NxU32 lineLength;
NxVec3 normal;
};
Then I declare the pointer:
CuttingLine* cuttingLines;
I initialize the pointer like this:
cuttingLines = (CuttingLine*)malloc(sizeof(CuttingLine) * 10);
And then I add some elements to it (please notice that this is just for demonstration purposes, in my program, line is created and given values):
for(int i=0;i<3;i++)
cuttingLines[i] = line;
Then I want to go through the pointer again, and delete the three elements, but not free the pointer (I understand that you can delete the pointer by calling free(cuttingLines)).
How can I do that? I just want to delete the elements inside it, but not deallocate the memory allocated in the beginning.
Because cuttingLines is a pointer to CuttingLine, your loop is actually performing a structure copy of line into each of the three positions. There is no need to delete these deep copies. You just have to not use the information anymore when you are done with it, and note that the cuttingLines variable contains unused data. You can then reuse the cuttingLines variable later (filling it with new lines) at your convenience.
To me it looks like you want to have an array of pointers, and dynamically allocate the elements of the array. In this case you'd want to set the value of the pointer to NULL, which means the pointer doesn't point to anything. Like this:
cuttingLines[i] = NULL;
This means "I have a pointer in my array but it doesn't point to anything".
However if you don't free the memory (by calling free(cuttingLines[i])) you will have a memory leak, so remember to free the memory later in your program. For this you will need to have another pointer somewhere that points to whatever each call to malloc returned.
Just to be pedantic: you can't free a pointer (except in the sense of allocating e.g. sizeof(CuttingLine*) using malloc); you can free memory, so calling free(ptr) frees the memory pointed to by the pointer. Also, you treat cuttingLines like an array of pointers, i.e. pointer of pointers, so its type should be CuttingLine** and you'd declare and allocate it by:
CuttlingLine** cuttingLines;
cuttingLines = (CuttingLine**)malloc(sizeof(CuttingLine*) * 10);
Also, you shouldn't cast the return value of malloc (see here) unless you're writing C++ in which case you shouldn't need to use pointers to pointers in the first place.
If on the other hand you want to have an array of CuttingLines then you're on the right track in the sense that you allocate cuttingLines correctly, and you don't need to free the memory used by individual CuttingLine. However in this case you don't know which elements in the array are valid and which aren't unless you either track the indices in the code or in the elements themselves by e.g. setting lineLength to 0 and checking its value.

Malloc or normal array definition?

When shall i use malloc instead of normal array definition in C?
I can't understand the difference between:
int a[3]={1,2,3}
int array[sizeof(a)/sizeof(int)]
and:
array=(int *)malloc(sizeof(int)*sizeof(a));
In general, use malloc() when:
the array is too large to be placed on the stack
the lifetime of the array must outlive the scope where it is created
Otherwise, use a stack allocated array.
int a[3]={1,2,3}
int array[sizeof(a)/sizeof(int)]
If used as local variables, both a and array would be allocated on the stack. Stack allocation has its pros and cons:
pro: it is very fast - it only takes one register subtraction operation to create stack space and one register addition operation to reclaim it back
con: stack size is usually limited (and also fixed at link time on Windows)
In both cases the number of elements in each arrays is a compile-time constant: 3 is obviously a constant while sizeof(a)/sizeof(int) can be computed at compile time since both the size of a and the size of int are known at the time when array is declared.
When the number of elements is known only at run-time or when the size of the array is too large to safely fit into the stack space, then heap allocation is used:
array=(int *)malloc(sizeof(int)*sizeof(a));
As already pointed out, this should be malloc(sizeof(a)) since the size of a is already the number of bytes it takes and not the number of elements and thus additional multiplication by sizeof(int) is not necessary.
Heap allocaiton and deallocation is relatively expensive operation (compared to stack allocation) and this should be carefully weighted against the benefits it provides, e.g. in code that gets called multitude of times in tight loops.
Modern C compilers support the C99 version of the C standard that introduces the so-called variable-length arrays (or VLAs) which resemble similar features available in other languages. VLA's size is specified at run-time, like in this case:
void func(int n)
{
int array[n];
...
}
array is still allocated on the stack as if memory for the array has been allocated by a call to alloca(3).
You definately have to use malloc() if you don't want your array to have a fixed size. Depending on what you are trying to do, you might not know in advance how much memory you are going to need for a given task or you might need to dynamically resize your array at runtime, for example you might enlarge it if there is more data coming in. The latter can be done using realloc() without data loss.
Instead of initializing an array as in your original post you should just initialize a pointer to integer like.
int* array; // this variable will just contain the addresse of an integer sized block in memory
int length = 5; // how long do you want your array to be;
array = malloc(sizeof(int) * length); // this allocates the memory needed for your array and sets the pointer created above to first block of that region;
int newLength = 10;
array = realloc(array, sizeof(int) * newLength); // increase the size of the array while leaving its contents intact;
Your code is very strange.
The answer to the question in the title is probably something like "use automatically allocated arrays when you need quite small amounts of data that is short-lived, heap allocations using malloc() for anything else". But it's hard to pin down an exact answer, it depends a lot on the situation.
Not sure why you are showing first an array, then another array that tries to compute its length from the first one, and finally a malloc() call which tries do to the same.
Normally you have an idea of the number of desired elements, rather than an existing array whose size you want to mimic.
The second line is better as:
int array[sizeof a / sizeof *a];
No need to repeat a dependency on the type of a, the above will define array as an array of int with the same number of elements as the array a. Note that this only works if a is indeed an array.
Also, the third line should probably be:
array = malloc(sizeof a);
No need to get too clever (especially since you got it wrong) about the sizeof argument, and no need to cast malloc()'s return value.

Resources