Initially mallocate 0 elements to later reallocate and measure size - c

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.

Related

How use local array in function - ANSI C?

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

malloc operation clears other allocated memory

I'm trying to make a program that basically picks a specific piece of source code and adds some other specific code into it. The program is just to big to put it all inside my question, but basically I have this "actors" struct:
typedef struct actors_s {
int num;
char *src_path;
char *project_path;
int *papify;
char *actor_path[];
} actors_s;
As you can see these are almost all pointers and the last one is an array of strings. This needs to be done this way because the number of "actor elements" depends on the input every time.
The problem:In an specific test case, I have a case with 'num' members in the actor_path array. Then I first call malloc only once this way:
*actors->actor_path = malloc(actors->num);
My logic tells me I shouldn't be using the '*' operator here but without it I get an error, this is possibly where the problem is. So, a function is called that allocates a new memory space for every new member (never going further of 'num' members):
int size = strlen(name)+strlen(actors->project_path)+strlen("/src/")+strlen(".c")+4;
actors->actor_path[i] = malloc(size);
(The malloc calls are properly tested if successful in the actual program)
This is called inside a function that is called for every "actor_path" element. In this test example I have three actors.
Mysteriously enough, on the third call of this malloc, the src_path element of the struct, which was properly allocated and set to a string once in the beginning of the program (and never touched again) is freed (I think so, at least it is changed into random numbers and symbols if I watch it in debug mode).
Anyone has any idea how and why is this possible? How do I fix this?
Thanks in advance.
EDIT:
Here are some screenshots from the debug watch window: http://imgur.com/a/aB1uv
First call to malloc: all OK.
Second call to malloc: all OK.
Third call to malloc: src_path gets erased!!
[] in latest array element is called flexible array member. It means structure have an array that starts just after structure itself, and its size is unspecified. You have to allocate memory for this manually. E.g.
actors_s *actor = malloc(sizeof(*actor) + sizeof(char*) * num);
Then just assign at most num elements into actor_path (each element is pointer to char).
about *actors->actor_path = malloc(actors->num);
actors->actor_path is an array of pointers, so *actors->actor_path is the first pointer in actors->actor_path, i.e. actors->actor_path[0].
When doing this, you actually allocate actors->num bytes memory for actors->actor_path[0].
Now, accessing actors->actor_path[0] is OK, while accessing actors->actor_path[1], actors->actor_path[2], actors->actor_path[3],... may cause problems, say, rewrite src_path...
about the solution
#keltar is right. In this way, the resource for actors->actor_path[0], actors->actor_path[1], actors->actor_path[2], ..., actors->actor_path[num - 1] is correctly allocated.

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.

Dynamic Array printing

I am trying to print a dynamic array, but I am having trouble with the bounds for the array.
For a simple example, lets say I'm trying to loop through an array of ints. How can I get the size of the array? I was trying to divide the size of the array by the size of the type like this sizeof(list)/sizeof(int) but that was not working correctly. I understand that I was trying to divide the size of the pointer by the type.
int *list
// Populate list
int i;
for(i = 0; i < ????; i++)
printf("%d", list[i]);
With dynamic arrays you need to maintain a pointer to the beginning address of the array and a value that holds the number of elements in that array. There may be other ways, but this is the easiest way I can think of.
sizeof(list) will also return 4 because the compiler is calculating the size of an integer pointer, not the size of your array, and this will always be four bytes (depending on your compiler).
YOU should know the size of the array, as you are who allocated it.
sizeof is an operator, which means it does its job at compile time. It will give you the size of an object, but not the length of an array.
So, sizeof(int*) is 32/62-bit depending on architecture.
Take a look at std::vector.
There is no standardized method to get the size of allocated memory block. You should keep size of list in unsigned listSize like this:
int *list;
unsigned listSize;
list = malloc(x * sizeof(int));
listSize = x;
If you are coding in C++, then it is better to use STL container like std::vector<>
As you wrote, you really did tried to divide the size of a pointer since list is declared as a pointer, and not an array. In those cases, you should keep the size of the list during the build of it, or finish the list with a special cell, say NULL, or anything else that will not be used in the array.
Seeing some of the inapropriate links to C++ tools for a C question, here is an answer for modern C.
Your ideas of what went wrong are quite correct, as you did it you only have a pointer, no size information about the allocation.
Modern C has variable length arrays (VLA) that you can either use directly or via malloc. Direcly:
int list[n];
and then your idea with the sizeof works out of the box, even if you changed your n in the mean time. This use is to be taken with a bit of care, since this is allocated on the stack. You shouldn't reserve too much, here. For a use with malloc:
int (list*)[n] = malloc(*list);
Then you'd have to adapt your code a bit basically putting a (*list) everywhere you had just list.
If by size you mean the number of elements then you could keep it in a counter that gets a ++ each time you push an element or if you dont mind the lost cycles you could make a function that gets a copy of the pointer to the first location, runs thru the list keeping a counter until it finds a k.next==null. or you could keep a list that as a next and a prev that way you wouldnt care if you lost the beginning.

List parameters in recursive calls (C)

I'm designing a recursive algorithm :
int f(int[] a, int[] b){
----changing a here
----changing b here
f(a,b)
----writing a here
----writing b here
}
I know all arrays are pointers so this code should be problematic. It'll write the final values of a and b after all the recursive calls finished. I dont want that to happen.
What should I do to pass that array to recursive calls as regular "pass by value"?
PS: Arrays may be dynamically allocated or resized etc anywhere in recursive calls.
I will assume that int f(int[] a, int[] b) is a typo: it should be int f(int a[], int b[]).
First of all, arrays and pointers are different. Under many circumstances, the name of an array "decays" to a pointer to its first element, but not always. Otherwise, sizeof a, for an array a wouldn't "work".
Secondly, let's ignore recursion for a moment. Let's also make the function prototype simpler:
int g(int *a);
(I changed int a[] to int *a, because in this context, the name of an array is equivalent to a pointer.)
Now, you say that you may "dynamically allocate or resize" the array in the function call. Since everything is passed by value in C, a dynamic allocation or resizing of a inside g() cannot be seen by the caller: the caller would still have the old value of a. But more importantly, if the "original" type of a was an array, i.e., the caller had code like:
int data[SIZE];
g(data);
then trying to resize data in g() is bad, because the parameter specified in the call wasn't dynamically allocated to begin with. You can only dynamically resize something that was the result of malloc(), calloc(), or realloc().
So, there are two problems even with this simple definition:
If g() has to dynamically resize the memory referred to by the address it is given, the value has to come from a dynamic allocation, not an array,
After fixing that, since g() wants to be able to signal the change to the caller, you need to pass a pointer to what needs to be changed. So, the prototype of g() becomes: int g(int **a);.
Hopefully the above will help you get started. If you tell us more about your algorithm, in particular, what you mean by: "changing" and "writing", you will get better responses.
Edit: to answer your question in the comment:
So when I passed an array to a function it decays to a pointer and this pointer is passed by value. If that pointer is pointing a place I allocated before that call...
If you allocated something before the call, it never was an array to begin with. It can be indexed as an array, but that's not the point. So, maybe you are getting confused by the terminology here?
...when my new function changes the pointed value then that value is changed at caller, too.
The pointed-to value is changed, yes.
I dont want it to be like this, so I need a copy of the pointed value in the new function so that my original pointer's pointed value would not change. am I clear now?
It's clearer now, but then that raises more questions:
If you are going to dynamically allocate or resize the data in each call to the function, how are you going to return those new pointers? You can't. And that means you have got yourself a memory leak. Unless you free() the data in the (recursively called) function itself.
How would you resize the pointer? You may not be able to know the size of the data pointed to, unless you use a sentinel value.
Are you using the function to iteratively solve a puzzle or a problem? Are you free()ing your data in each invocation of the function? If you can tell us, exactly what are you trying to do?
All arrays are not pointers.
See these:
http://c-faq.com/aryptr/practdiff.html
http://c-faq.com/aryptr/aryptrequiv.html
http://c-faq.com/aryptr/ptrkindofary.html - specifically this one
Assuming you want the order of the output to be the same as in your original, if you don't want the outer call to see changes to your arrays made in the recursive call, you need to copy them. The easiest way is probably to allocate them on the stack then memcopy from the argument, though that will cause a SO if it gets too big. The second easiest is to malloc and free them. You will probably need to pass the array size around too. You can't pass arrays by value on the stack in C.
Just print them before passing them to the next level of recursion.
Your question isn't terribly clear but what I'm reading is this:
You have a recursive algorithm that operates on two heap-allocated arrays. It is possible that one of the recursive calls will have to reallocate the arrays, and so when it returns to the next level up, the old pointers won't be valid anymore. You want to know how to "pass the arrays by value" in order to avoid this.
First, you cannot pass an array by value in C. Period. Arrays are always passed as pointers to the first element, and there's no way around that.
Second, the answer is always another level of indirection. :)
In order to solve the problem of having to reallocate the arrays during the recursive call, what you want to do is have the function take two pointer-to-pointers (int**), where *a gives the address of the pointer to the first element of the A array, and (*a)[n] gives the nth element of the a array. That way, you can reallocate the array to your heart's content, (changing the value of *a) but the value of a itself always remains the same. By doing this, instances of the function further up the call stack will automatically inherit the reallocations made by the recursive calls because the pointed-to value (*a) of the pointer (a) that they passed to the recursive call was modified to reflect the new location of the actual data.
e.g.
int f(int** a, int** b)
{
/* Do stuff on arrays using (*a)[n] and (*b)[n] */
if (some_condition) {
/* Time to reallocate */
*a = realloc(*a, new_size);
*b = realloc(*b, new_size);
}
/* Do stuff on arrays using (*a)[n] and (*b)[n] */
f(a, b); /* Recursive call */
/* Do more stuff using (*a)[n] and (*b)[n] */
/* a and b are still valid pointers, even though *a and *b might point somewhere new */
return foo;
}
void use_f(void)
{
int* a = malloc(starting_size);
int* b = malloc(starting_size);
f(&a, &b);
}
Given the requirements:
int f(int[] a, int[] b){
----changing a here
----changing b here
f(a,b)
----writing a here
----writing b here
}
What should I do to pass that array to recursive calls as regular "pass by value"?
PS: Arrays may be dynamically allocated or resized etc anywhere in recursive calls.
The code in f() is either authorized to make changes to the arrays (as now), or it is not authorized to make changes. If it is authorized to make changes, then there is nothing much you need to do, except worry about whether you are going to leak memory if you are using dynamic allocation.
If the code is not authorized to change the arrays, then it will have to make copies of the arrays. You can prevent the code from casually modifying them by including appropriate const qualifiers:
int f(const int *a, const int *b) { ... }
Note that you cannot pass arrays by value in C. You could have the caller pass a modifiable copy - or you can have the receiver (callee?) make the copy; one or the other will have to o so if the receiver is going to make modifications when it shouldn't.
The easiest and safest option is to pass a pointer and a size. Say you are working on something like quick-sort:
void sort_range( int* ptr, size_t count )
{
size_t pivot;
assert( ptr ); /* make sure we have memory */
if ( count < 2 ) return; /* terminate recursion */
pivot = partition( count ); /* select a pivot */
assert( pivot < count ); /* make sure we don't overrun the buffer */
sort_range( ptr, pivot ); /* sort left part */
sort_range( ptr + pivot, count - pivot ); /* sort right part */
merge( ptr, count, pivot ); /* merge ranges */
}
Always be conscious about size of the memory chunk you are working with. Unfortunately C doesn't make it easy, so you have to develop a habit of checking your memory ranges.

Resources