Free array of pointers - c

I have this test code :
void test2(){
char** twoDArray = (char**)calloc(3,sizeof(char*));
char* element1 = (char*)calloc(3,sizeof(char));
twoDArray[0] = element1;
twoDArray[1] = element1;
twoDArray[2] = element1;
freeArray(twoDArray,3);
}
void freeArray(char** arr,int size){
if(arr!= NULL){
for(int i =0 ;i < size;i++){
if(arr[i] != NULL){
free(arr[i]);
arr[i] = NULL;
}
}
free(arr);
arr = NULL;
}
}
in second iteration of loop in freeArray arr[1] != NULL give 'true' and error occurs, why ? How to properly free such array ?

Do not cast the return value of calloc()!
You are assigning the very same pointer to each element of the array. I don't know why/how you expect it to work (because then you won't have a 2D-like array, since setting one element of a row will change the element at the same column in all other rows too...)
If you still stick to this design, then you should free the inner "array" only once.
But I suspect you wanted to emulate a sane, working, sensible 2D-array. In this case, you have two options:
I. The hackish solution: almost the same as yours, but you need to callocate memory for each row in a separate step, like this:
twoDArray[0] = calloc(3, sizeof(twoDArray[0]));
twoDArray[1] = calloc(3, sizeof(twoDArray[0]));
twoDArray[2] = calloc(3, sizeof(twoDArray[0]));
(or perhaps use a loop... if you know what they are.)
II. The correct solution: why not allocate a continuous block of memory and avoid all superfluous calls to calloc() and all headache as to what and when needs to be free()d? One array -> one allocation, one deallocation:
char (*arr[3]) = calloc(3, sizeof(arr[0]));
// ...
free(arr);
Nice, simple and more maintainable.

If you are going to make the freeArray function, you have to define some rules about what the array must contain. Your implementation of freeArray makes the assumption that each element of the array is pointing to a separately allocated array of characters, however each element of the array is actually pointing to the same array of characters, so you end up trying to free the same array multiple times, which is not valid.
If freeArray's assumptions are correct, then you'll need to modify how you create the array. If freeArray's assumptions are not correct, you'll need to modify freeArray.

Related

C dynamically allocate struct array and its components

What is the correct approach to dynamically allocate a struct array and its components in C? I have managed to do something that works,but I am kind of sceptical if it is correct.
I have the following code:
This is my struct array that I need to dynamically allocate:
typedef struct
{
char *wrong;
char *right;
}Dictionary;
This is the function I call when I need to initialise my struct array:
Dictionary *init_Dictionary(int nr_elem)
{
Dictionary *dict;
dict = malloc(nr_elem*sizeof(Dictionary));
for(int i=0; i<nr_elem; i++)
{
char wrong[101],right[101];
scanf("%s%s",wrong,right);
dict[i].wrong = malloc(strlen(wrong)*sizeof(char));
dict[i].right = malloc(strlen(right)*sizeof(char));
strcpy(dict[i].wrong,wrong);
strcpy(dict[i].right,right);
}
return dict;
}
Then in my main function, I have this:
int nr_elem;
scanf("%d",&nr_elem);
Dictionary *dict;
dict = init_Dictionary(nr_elem);
Also,when I finish work with the struct, how do I free the used memory ?
EDIT Thank you all for the quick and indepth answers!
For each allocation you need to allocate one more location to allow for \0 (NULL terminator) at the end of the string.
dict[i].wrong = malloc(strlen(wrong)*sizeof(char) +1 );
dict[i].right = malloc(strlen(right)*sizeof(char) +1);
To free, you first need to free all the pointers right and wrong in the array and then free the main dict array. Optionally, you can NULL the pointers after free.
Dictionary* freeDict(Dictionary *dict, int nr_elem)
{
for (int i=0; i<nr_elem; i++)
{
free(dict->wrong);
free(dict->right);
dict->wrong = NULL;
dict->right = NULL;
}
free (dict);
dict = NULL;
return dict;
}
//To call.
dict = free(dict, nr_elem);
The program design isn't good, you should separate UI from algorithms. Instead of this, you should first take the user input, then store it in 2 strings and pass the strings as parameters to init_Dictionary.
As for the allocation, it is almost correct. But you forgot to allocate space for the null terminator, it should be:
dict[i].wrong = malloc(strlen(wrong)+1);
dict[i].right = malloc(strlen(right)+1);
Multiplying with sizeof(char) isn't meaningful, since the definition of sizeof(char) is always 1 on all systems.
In a production-quality application, you must always check the result of each malloc, then handle errors.
You free memory the same way as you allocated it, but in the opposite order since you need dict itself to be valid until you have deallocated its members:
for(int i=0; i<nr_elem; i++)
{
free(dict[i].wrong);
free(dict[i].right);
}
free(dict);
As a rule of thumb, each call to malloc must be matched with a call to free.
There's a bug in your implementation: strlen(s) does not count the terminating 0-character, so, despite one test may work successfully, this is actually an UB. strdup can do work for you; if you don't have it standard library, simply add 1 when allocating memory for string copies. Or even better: count string length once, then use this value to both allocate enough bytes and copy contents with memcpy.
Otherwise your algorithm is quite useful (provided an array of string pairs is really what you need, with no additional structure like search index or anything).
To deallocate it, add a destructor that performs element-wise deallocation and then frees the whole array:
void destroy(Dictionary *dict, size_t nr_elem) {
for(size_t i = 0; i < nr_elem; ++i) {
free(dict[i].wrong);
free(dict[i].right);
}
free(dict);
}

How to return a char** in C

I've been trying for a while now and I can not seem to get this working:
char** fetch (char *lat, char*lon){
char emps[10][50];
//char** array = emps;
int cnt = -1;
while (row = mysql_fetch_row(result))
{
char emp_det[3][20];
char temp_emp[50] = "";
for (int i = 0; i < 4; i++){
strcpy(emp_det[i], row[i]);
}
if ( (strncmp(emp_det[1], lat, 7) == 0) && (strncmp(emp_det[2], lon, 8) == 0) ) {
cnt++;
for (int i = 0; i < 4; i++){
strcat(temp_emp, emp_det[i]);
if(i < 3) {
strcat(temp_emp, " ");
}
}
strcpy(emps[cnt], temp_emp);
}
}
}
mysql_free_result(result);
mysql_close(connection);
return array;
Yes, I know array = emps is commented out, but without it commented, it tells me that the pointer types are incompatible. This, in case I forgot to mention, is in a char** type function and I want it to return emps[10][50] or the next best thing. How can I go about doing that? Thank you!
An array expression of type T [N][M] does not decay to T ** - it decays to type T (*)[M] (pointer to M-element array).
Secondly, you're trying to return the address of an array that's local to the function; once the function exits, the emps array no longer exists, and any pointer to it becomes invalid.
You'd probably be better off passing the target array as a parameter to the function and have the function write to it, rather than creating a new array within the function and returning it. You could dynamically allocate the array, but then you're doing a memory management dance, and the best way to avoid problems with memory management is to avoid doing memory management.
So your function definition would look like
void fetch( char *lat, char *lon, char emps[][50], size_t rows ) { ... }
and your function call would look like
char my_emps[10][50];
...
fetch( &lat, &lon, my_emps, 10 );
What you're attempting won't work, even if you attempt to cast, because you'll be returning the address of a local variable. When the function returns, that variable goes out of scope and the memory it was using is no longer valid. Attempting to dereference that address will result in undefined behavior.
What you need is to use dynamic memory allocation to create the data structure you want to return:
char **emps;
emps = malloc(10 * sizeof(char *));
for (int i=0; i<10; i++) {
emps[i] = malloc(50);
}
....
return emps;
The calling function will need to free the memory created by this function. It also needs to know how many allocations were done so it knows how many times to call free.
If you found a way to cast char emps[10][50]; into a char * or char **
you wouldn't be able to properly map the data (dimensions, etc). multi-dimensional char arrays are not char **. They're just contiguous memory with index calculation. Better fit to a char * BTW
but the biggest problem would be that emps would go out of scope, and the auto memory would be reallocated to some other variable, destroying the data.
There's a way to do it, though, if your dimensions are really fixed:
You can create a function that takes a char[10][50] as an in/out parameter (you cannot return an array, not allowed by the compiler, you could return a struct containing an array, but that wouldn't be efficient)
Example:
void myfunc(char emp[10][50])
{
emp[4][5] = 'a'; // update emp in the function
}
int main()
{
char x[10][50];
myfunc(x);
// ...
}
The main program is responsible of the memory of x which is passed as modifiable to myfunc routine: it is safe and fast (no memory copy)
Good practice: define a type like this typedef char matrix10_50[10][50]; it makes declarations more logical.
The main drawback here is that dimensions are fixed. If you want to use myfunc for another dimension set, you have to copy/paste it or use macros to define both (like a poor man's template).
EDITa fine comment suggests that some compilers support variable array size.
So you could pass dimensions alongside your unconstrained array:
void myfunc(int rows, int cols, char emp[rows][cols])
Tested, works with gcc 4.9 (probably on earlier versions too) only on C code, not C++ and not in .cpp files containing plain C (but still beats cumbersome malloc/free calls)
In order to understand why you can't do that, you need to understand how matrices work in C.
A matrix, let's say your char emps[10][50] is a continuous block of storage capable of storing 10*50=500 chars (imagine an array of 500 elements). When you access emps[i][j], it accesses the element at index 50*i + j in that "array" (pick a piece of paper and a pen to understand why). The problem is that the 50 in that formula is the number of columns in the matrix, which is known at the compile time from the data type itself. When you have a char** the compiler has no way of knowing how to access a random element in the matrix.
A way of building the matrix such that it is a char** is to create an array of pointers to char and then allocate each of those pointers:
char **emps = malloc(10 * sizeof(char*)); // create an array of 10 pointers to char
for (int i = 0; i < 10; i++)
emps[i] = malloc(50 * sizeof(char)); // create 10 arrays of 50 chars each
The point is, you can't convert a matrix to a double pointer in a similar way you convert an array to a pointer.
Another problem: Returning a 2D matrix as 'char**' is only meaningful if the matrix is implemented using an array of pointers, each pointer pointing to an array of characters. As explained previously, a 2D matrix in C is just a flat array of characters. The most you can return is a pointer to the [0][0] entry, a 'char*'. There's a mismatch in the number of indirections.

Memory leak in C

I am using GTK, and I am not sure with malloc() function here. Valgrind gives me a memory leak, what I am doing bad?
at first I create pointer to pointer to pointer to GTK widget, because I need three dimensional array.
GtkWidget*** widgets;
and I am using malloc like this:
widgets = malloc((1)*sizeof(GtkWidget**));
for(i = 0; i<= l-1; i++) // l = 4 in my case
{
widgets[i] = malloc((1)*sizeof(GtkWidget*));
for(j = 0; j<=3; j++) // 4 is number of elements in this dimension
{
widgets[i][j] = malloc((1)*sizeof(GtkWidget));
}
}
and at the end I am doing this:
widgets[0][0] = gtk_menu_item_new_with_label("MyLabel");
gtk_menu_shell_append(GTK_MENU_SHELL(indicator_menu), widgets[0][0]);
my array can be smaller and bigger, so I am using dynamic allocation of array, my maximal array indexes are something like widgets[3][3].
I did not post whole code, because it is pretty long, I sent here just the parts for which was valgrind complaining to. What I am doing bad? thank you.
You're only allocating the size of a pointer, when you mean to allocate an array of pointers.
// this will allocate a single character pointer
char ** ptr = malloc(1 * sizeof(char *));
// this will allocate n character pointers
char ** ptr = malloc(n * sizeof(char *));
So if you want a two dimensional array of dimension NxM, you'll need to allocate an array of size N, then walk through that array from 0 to N-1 and allocate arrays of size M.
What you're doing now is assigning pointers returned from malloc to memory you don't own. Is what you actually want a two-dimensional array of pointers to GtkWidget structures?
Using l as a local variable is not a good idea. It is very easy to make a mistake between l and 1, in some editors they look very much the same.
widgets = malloc((l)*sizeof(GtkWidget**)); //is what you needed
iso
widgets = malloc((1)*sizeof(GtkWidget**));
Over here with syntax highlighting the problem immediately appears.
So another suggestion is to for sure use an editor with syntax highlighting

C using malloc and duplicating array

I am supposed to follow the following criteria:
Implement function answer4 (pointer parameter and n):
Prepare an array of student_record using malloc() of n items.
Duplicate the student record from the parameter to the array n
times.
Return the array.
And I came with the code below, but it's obviously not correct. What's the correct way to implement this?
student_record *answer4(student_record* p, unsigned int n)
{
int i;
student_record* q = malloc(sizeof(student_record)*n);
for(i = 0; i < n ; i++){
q[i] = p[i];
}
free(q);
return q;
};
p = malloc(sizeof(student_record)*n);
This is problematic: you're overwriting the p input argument, so you can't reference the data you were handed after that line.
Which means that your inner loop reads initialized data.
This:
return a;
is problematic too - it would return a pointer to a local variable, and that's not good - that pointer becomes invalid as soon as the function returns.
What you need is something like:
student_record* ret = malloc(...);
for (int i=...) {
// copy p[i] to ret[i]
}
return ret;
1) You reassigned p, the array you were suppose to copy, by calling malloc().
2) You can't return the address of a local stack variable (a). Change a to a pointer, malloc it to the size of p, and copy p into. Malloc'd memory is heap memory, and so you can return such an address.
a[] is a local automatic array. Once you return from the function, it is erased from memory, so the calling function can't use the array you returned.
What you probably wanted to do is to malloc a new array (ie, not p), into which you should assign the duplicates and return its values w/o freeing the malloced memory.
Try to use better names, it might help in avoiding the obvious mix-up errors you have in your code.
For instance, start the function with:
student_record * answer4(const student_record *template, size_t n)
{
...
}
It also makes the code clearer. Note that I added const to make it clearer that the first argument is input-only, and made the type of the second one size_t which is good when dealing with "counts" and sizes of things.
The code in this question is evolving quite quickly but at the time of this answer it contains these two lines:
free(q);
return q;
This is guaranteed to be wrong - after the call to free its argument points to invalid memory and anything could happen subsequently upon using the value of q. i.e. you're returning an invalid pointer. Since you're returning q, don't free it yet! It becomes a "caller-owned" variable and it becomes the caller's responsibility to free it.
student_record* answer4(student_record* p, unsigned int n)
{
uint8_t *data, *pos;
size_t size = sizeof(student_record);
data = malloc(size*n);
pos = data;
for(unsigned int i = 0; i < n ; i++, pos=&pos[size])
memcpy(pos,p,size);
return (student_record *)data;
};
You may do like this.
This compiles and, I think, does what you want:
student_record *answer4(const student_record *const p, const unsigned int n)
{
unsigned int i;
student_record *const a = malloc(sizeof(student_record)*n);
for(i = 0; i < n; ++i)
{
a[i] = p[i];
}
return a;
};
Several points:
The existing array is identified as p. You want to copy from it. You probably do not want to free it (to free it is probably the caller's job).
The new array is a. You want to copy to it. The function cannot free it, because the caller will need it. Therefore, the caller must take the responsibility to free it, once the caller has done with it.
The array has n elements, indexed 0 through n-1. The usual way to express the upper bound on the index thus is i < n.
The consts I have added are not required, but well-written code will probably include them.
Altought, there are previous GOOD answers to this question, I couldn't avoid added my own. Since I got pascal programming in Collegue, I am used to do this, in C related programming languages:
void* AnyFunction(int AnyParameter)
{
void* Result = NULL;
DoSomethingWith(Result);
return Result;
}
This, helps me to easy debug, and avoid bugs like the one mention by #ysap, related to pointers.
Something important to remember, is that the question mention to return a SINGLE pointer, this a common caveat, because a pointer, can be used to address a single item, or a consecutive array !!!
This question suggests to use an array as A CONCEPT, with pointers, NOT USING ARRAY SYNTAX.
// returns a single pointer to an array:
student_record* answer4(student_record* student, unsigned int n)
{
// empty result variable for this function:
student_record* Result = NULL;
// the result will allocate a conceptual array, even if it is a single pointer:
student_record* Result = malloc(sizeof(student_record)*n);
// a copy of the destination result, will move for each item
student_record* dest = Result;
int i;
for(i = 0; i < n ; i++){
// copy contents, not address:
*dest = *student;
// move to next item of "Result"
dest++;
}
// the data referenced by "Result", was changed using "dest"
return Result;
} // student_record* answer4(...)
Check that, there is not subscript operator here, because of addressing with pointers.
Please, don't start a pascal v.s. c flame war, this is just a suggestion.

Assigning an address to a struct pointer array member in C

Having considerable trouble with some pointer arithmatic. I think I get the concepts (pointer variables point to a memory address, normal variables point to data) but I believe my problem is with the syntax (*, &, (*), *(), etc.)
What I want to do is build dynamic arrays of a custom struct (i.e. arrays of pointers to heap structs), and my interface provides two methods, "ad_to_obj_array" (which takes the object to add and the array which can be null for empty) and "obj_array_dustbin" (which just takes the array to dispose, also disposing of the contents, the heap objs). The former is rendered below.
The details of the objects are not important (and the struct has been renamed anyway) but my solution to the general problem is below, and I'd be grateful if you can spot the error. The compiler is complaining about an invalid lvalue, where I try and assign the address in the pointer on the RHS to the pointer value in an array of pointers to heap structs:
#define NUM_ELEM(x) (sizeof (x) / sizeof (*(x)))
obj* add_to_obj_array(obj* new_obj, obj* array)
{
int number_of_elements = 0;
if (array != NULL)
{
number_of_elements = NUM_ELEM(array);
}
obj* new_array = NULL;
/* note: I am expecting sizeof(new_obj) to return the size of an obj*
to go into the array of pointers. */
if ( NULL ==
(new_array = (obj*)malloc((number_of_elements + 1)* sizeof(new_obj))) )
{
/* memory request refused :( */
return NULL;
}
/* copy the old array pointers into the new array's pointer slots: */
int i;
for (i = 0; i < number_of_elements; i++)
{
&(new_array[i]) = &(array[i]);
}
/* add the new item to the end (assign pointer value directly): */
new_array[number_of_elements] = new_obj;
if (number_of_elements > 0)
{
free(&array);
}
return new_array;
}
Now, I have tried the following permutations of the offending line:
&(new_array[i]) = &(array[i]);
*(new_array[i]) = &(array[i]);
new_array[i] = &(array[i]);
and all give a compiler error of one sort or another. I am fairly sure that the right hand side is the address of the ith element of the old array, but how to I assign to the ith element of the new, when the elements of the array are pointers to structs?
EDIT - please note, the macro NUM_ELEM above DOES NOT WORK; it will always return 1. See #Merlyn Morgan-Graham's answer below for why.
Based on your description, you're starting off wrong, so by the time you get to copying things, nothing you can do is likely to work.
Right now, you've defined new_array (and, presumably, array) as a pointer to obj. The result looks like this:
In this case, you have a pointer to a dynamically allocated array of objects. When/if you expand the allocation, you'll need to copy all the objects themselves.
According to your description: "(i.e. arrays of pointers to heap structs)", what you want is an array of pointers. If you want to allocate that array of pointers automatically, your definition would look like:
obj *array[NUMBER];
My guess is that's not what you want though. Presumably, you want to allocate that array dynamically as well. That would look like this:
In this case, new_array and array will each need to be defined as a pointer to pointer to obj. You'd then allocate an array of pointers (i.e., pointers to as many objs as you want) and have each point point at an obj:
obj **new_array;
// allocate an array of pointers with space to point at more items:
new_array = malloc(sizeof(obj *) * new_elements);
// copy the pointers to the current items to the new array:
for (i=0; i<current_elements; i++)
new_array[i] = array[i];
The advantage of this is that when you do the copying, you only copy pointers, not the objects themselves. Especially with large objects, this can save a substantial amount of effort. The tradeoff is that using an element goes through two levels of indirection intead of one, so the reference may be slower (though rarely much slower, especially on a relatively high-performance processor).
As #rerun already pointed out, in either case you probably want to use realloc. In particular, this might be able to expand an allocation "in place", and avoid copying data as often. Of course, that's not guaranteed, but at least you're giving it a chance; if you malloc and copy every time, you eliminate even the possibility of that optimization.
You have two arrays doesn't new_array[i] = array[i] do what you need.
Have you looked at realloc as a possible solution.
Just assign the values across. new_array[i] = array[i].
The problem you may be running into is that, for obj* to actually be an array of pointers, obj must itself be a pointer type:
typedef struct
{
int value1;
} obj_pool;
typedef obj_pool* obj;
int main(int argc, char* argv[])
{
obj_pool pool1;
pool1.value1 = 5;
obj array[] = { &pool1 };
array[0]->value1 = 16;
return 0;
}
Another problem you'll run into once you get this compiling is that sizeof(array) == sizeof(obj*). NUM_ELEM(array) will always return the same value. This means you'll have to pass a size_t array_size parameter to your function.
in your code elements of the array are not pointers on the structure, they are structure objects. elements of the this array obj** array are pointers on the structure obj.
#define NUM_ELEM(x) (sizeof (x) / sizeof (*(x)))
void add_to_obj_array(obj* new_obj, obj** array)
{
int number_of_elements = 0;
if (array != NULL)
{
number_of_elements = NUM_ELEM(array);
}
// expand array with one more item
array = (obj**)realloc(array, (number_of_elements + 1) * sizeof(new_obj));
if (array == NULL )
{
/* memory request refused :( */
return;
}
// Put new item at the last place on the array
array[number_of_elements] = new_obj;
}
So here we used matrix (pointer on pointers of the obj structure). When we add new element we simply expand existing array for one place and on that place we put new structure object. There is no need to return value because we operate on the pointers of the objects, and all change is done on actual objects, not on their copies.

Resources