I'm writing a function in C which adds a new product entry to an array of structs. The array is defined in the following structure:
struct product_array {
struct product *arr;
unsigned int count; //Initially set to NULL, counts the number of entries
};
The array is dynamically allocated, but each time a new entry is added it should be reallocated. Each element of an array consists of product structure:
struct product {
char *title;
char code[8]; // Should be truncated to 7 characters
};
This is what I wrote:
void add_product(struct product_array *pa, const char *title, const char *code)
{
pa->arr = realloc(pa->arr, sizeof(struct product) * (pa->count + 1));
if (pa->arr == NULL)
return NULL;
char *temp = malloc(strlen(title) + 1); // for title memory
//should be dynamically allocated separately
if (temp == NULL){
return NULL;
}
memmove(temp, title, (strlen(title) + 1));
title = temp;
pa->arr[pa->count].title = title;
int j = 0;
while (*code) {
pa->arr[pa->count].code[j] = (*code);
code++;
j++;
if (j == 7)
break;
}
pa->arr[pa->count].code[j] = '\0';
pa->count++;
}
It seems to work fine (though I'm not sure if I used realloc correctly). But now I'm supposed to release the memory. I did it by writing:
free(pa->arr);
It also seems to be okay. But now I'm supposed to release memory which was allocated for title. To do that I should change main.c.
int main()
{
struct product_array pa;
pa.count = 0;
pa.arr = NULL;
add_product(&pa, "Product 1", "1111");
add_product(&pa, "Product 2", "123320");
add_product(&pa, "Product 3", "565496845");
}
And here I'm lost.
free (pa.arr->title);
doesn't seem to work.
Would really appreciate your help.
Before freeing the pa->arr, you have to iterate over the array, freeing each structure's title separately, like this:
for (int i = 0; i < pa.count; ++i)
{
free(pa.arr[i].title);
}
free(pa.arr);
There are many problems there.
Be careful when using realloc: If you call realloc() and there is not enough room to enlarge the memory allocation pointed out it will copy everything to a new position, what may be slow. So, if the array is something that you expect to change it's size a lot, and you are not working in a platform that has tight memory size restrictions, you should do it in a different way. For example: allocate a space for 500 entries, and when it gets full, call a realloc to grow it to 1000 entries. This way you save some processing power (and memory bandwidth) by using more memory.
Also, make sure you understand how memory allocation works. A good reference is http://www-bcf.usc.edu/~dkempe/CS104/08-29.pdf
For example, if you call:
free(pa->arr);
Just the array will be freed, all the titles will be still allocated in memory, but you lost all the references to them. This is called memory leak (http://en.wikipedia.org/wiki/Memory_leak).
In your main() class, you allocated 3 different instances of 'title', when you go to free the memory, you need to free 3 different instances of 'title'. The simple answer is to just loop through pa->arr and free the title from each member.
One trick I used when writing 'C' is to create a function that deallocates the members of a struct. Then if you are allocating in an array like above, you just loop through the array calling the free_() function to free all the members of the struct.
void free_product(struct product *p) {
free (p->title);
/* If you dynamically allocate more fields in p, free them here */
}
void free_product_array(struct product_array *pa)
{
int i;
for (i = 0 ; i < pa->count; i++) {
free_product(&pa->arr[i]);
}
free (pa->arr);
}
Your case is a bit different that what I normally do. I usually free the pointer itself at the end of the function, but I wouldn't do that here because you allocated an entire array for your product entries at once.
Related
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);
}
I have some issue with my realloc function.
I have the struct Country and inside I have struct "City" which include point to cities array that every city is have 3 fields:
typedef struct Country {
char *name;
int numberOfCities;
City* cities;
cordinate cordinateOfCountryLeft;
cordinate cordinateOfCountryRight;
}Country;
typedef struct City
{
char *name;
char * popluarFood;
int numberOfPeople;
}City;
I need to delete city from the cities array so I free the city with function that I built called freeCity:
void freeCity(City *pCity)
{
free(pCity->name);
free(pCity->popluarFood);
free(pCity);
}
but after delete when I am trying to realloc I get error in this function when realloc
status freeCityFromCountry(Country *country, char *cityName)
{
for (int i = 0; i < country->numberOfCities; i++) {//for
if (strcmp(country->cities[i].name, cityName)==0)
{
freeCity(country->cities+i);
country->cities[i] = country->cities[country->numberOfCities - 1];
// free(country->cities[country->numberOfCities - 1]);
country->cities = (City*)realloc(country->cities,(country->numberOfCities-1));
country->numberOfCities--;
return success;
}
}//for
return failure;
}
I malloc country->cities in other function.
Where can the problem be?
You cannot call free on a pointer to the middle of an allocated chunk. country->cities points to a contiguous block in memory (N x sizeof(City)). A good rule of thumb is, if you have malloc(something), you must have (and can only have) free(something) somewhere else (malloc(country->cities) -> free(country->cities)).
The code crashes because the first call to freeCity frees country->cities. Perhaps you want .cities to be an array of pointers, i.e. City**, in that case you would allocate each City separately, and the cities array would then point to chunks which you can free individually.
Assuming that you allocate country->cities in another function.
You are calling freeCity(country->cities+i);
But in the freeCity function you are also freeing the city free(pCity);
So, for the cities array, you are calling free on city[i]. This has two issues
For the first loop, when i is 0, you are freeing the array and then reallocating it.
For the other iterations, when i is non zero, you are freeing at the wrong place. You should free the base of the array and not inside the array.
I'm trying to implement the first part of an autocomplete feature that takes in a string, calculates an index for a particular letter, and then allocates another struct pointer at that index. It also stores possible completions of words in a string array. For some reason, the program crashes when I try to access the string array field, and I can't figure out why. How can I fix this?
Thanks
struct table {
struct table *next[26];
char **complete;
int lastIndex;
int size;
};
static struct table Base={{NULL},NULL,0,0};
void insert(const char *string){
int index=string[0]-'a';
if(Base.next[index]==NULL){
Base.next[index]=(struct table*)malloc(sizeof(struct table));
*Base.next[index]=(struct table){{NULL},NULL,0,0};
}
struct table *pointer=Base.next[index];
if(pointer->lastIndex==pointer->size){ //expand complete array
pointer->complete[pointer->lastIndex] = strdup(string); //program crashes here
pointer->lastIndex=pointer->lastIndex+1;
}
}
The crash in this line
pointer->complete[pointer->lastIndex] = strdup(string);
is because pointer->complete is NULL. In other words, you forgot to allocate memory for complete.
How can I fix this?
You must allocate memory. It seems that you want a dynamic sized array of char pointers. So you'll need to use realloc so that you both extend the allocated memory and preserve previous values.
Something like:
char** tmp = realloc(pointer->complete, (pointer->lastIndex + 1) * sizeof(char*));
if (tmp == NULL)
{
// Out of memory
exit(1);
}
pointer->complete = tmp;
// Then you can do your normal code
pointer->complete[pointer->lastIndex] = strdup(string);
Notice: Though it's possible to use realloc every time you insert a string, it may perform rather bad.
So instead of reallocating memory for every new string, it may be better to reallocate a chunk of memory each time you call realloc. Like:
if (pointer->lastIndex == pointer->size)
{
// Need more memory
// - if it's the first time just start with 10 (or another number)
// - else double the size
pointer->size = (pointer->size != 0) ? 2 * pointer->size : 10;
char** tmp = realloc(pointer->complete, (pointer->size) * sizeof(char*));
if (tmp == NULL)
{
// Out of memory
exit(1);
}
pointer->complete = tmp;
}
Here I decided to double the allocated memory when doing realloc. You can of cause use ant approach you like instead, e.g. always add 10 more instead of doubling.
BTW: The name lastIndex seems poor as it's really a nextIndex variable.
A final word on data structure
Your data structur, i.e. struct table seems a bit strange to me. At base-level, you only use table. At the next level you don't use table but only the other variables.
Seems to me that you should split up the struct into two structs like:
struct StringTable {
char **complete;
int lastIndex;
int size;
};
struct table {
struct StringTable strings[26];
};
That would save you both memory and some of the dynamic memory allocation.
You are assuming that
const char * string
will contain only small case alphabets. Dictionaries also have apostrophes
add that case.
My code contains the struct BeforeTriag which is from type Patient** .
here is the structs and it's fields:
typedef struct{
char Id[ID_SIZE];
char Name[NAME_SIZE];
char LastName[NAME_SIZE];
char PhoneNum[PHONE_SIZE];
STATUS Status;
char Address[ADDRESS_SIZE];
}Patient;
Here is my initilization and allocation:
Patient** BeforeTriag = NULL;
int* BeforeTriagSize[1] = { 0 };
BeforeTriag = (Patient**)malloc(sizeof(Patient*));
if (!(BeforeTriag))
{
printf("ERROR!Out of memory!");
exit(1);
}
*BeforeTriag = (Patient*)malloc((PatientArraySize)* sizeof(Patient));
if (!(*BeforeTriag)){
printf("ERROR!Out of memory!");
exit(1);
}
here i'm tring to free each field in the struct:
for (i = 0; i < (*BeforeTriagSize); i++){
free((BeforeTriag)[i]->Id);
free((BeforeTriag)[i]->Name);
free((BeforeTriag)[i]->LastName);
free((BeforeTriag)[i]->Address);
free((BeforeTriag)[i]->PhoneNum);
}
free(BeforeTriag);
When I am debugging it crush on the first row of the free id:
free((BeforeTriag)[i]->Id);
What should i do to free as proper?
The individual fields within BeforeTriag[i] were not dynamically allocated by themselves, so you can't free them. You need to free the struct as a whole, because that's what was allocated:
for (i = 0; i < (*BeforeTriagSize); i++){
free(BeforeTriag[i]);
}
free(BeforeTriag);
You do not have to do this:
for (i = 0; i < (*BeforeTriagSize); i++){
free((BeforeTriag)[i]->Id);
free((BeforeTriag)[i]->Name);
free((BeforeTriag)[i]->LastName);
free((BeforeTriag)[i]->Address);
free((BeforeTriag)[i]->PhoneNum);
}
Because they are not dynamically allocated.
But you have to free BeforeTriag[i] inside the loop.
for (i = 0; i < (*BeforeTriagSize); i++){
free(BeforeTriag[i]);
}
free(BeforeTriag);
While #dbush and #RolBrok already pointed out correctly that there's no need to free the individual members, there is another bug in your code:
int* BeforeTriagSize[1] = { 0 };
This line initalizes a int ** to zero. I'm not really sure why you want this variable to be in an array, but anyway, the correct way to declare it would be
int BeforeTriagSize[1] = { 0 };
(If you only need one value for BeforeTriagSize anyway, just declare it as an int!)
Edit:
Another thing you should look closer into is the way you're allocating memory for your structs:
*BeforeTriag = (Patient*)malloc((PatientArraySize)* sizeof(Patient));
With this you're always writing to the same pointer. So when you are allocating the memory for the second struct, you are overwriting the position of the first one, basically causing a memory leak.
Consider something along the line of
BeforeTriag[BeforeTriagSize++] = (Patient*)malloc((PatientArraySize)* sizeof(Patient));
This ensures that you are writing to a new position in your array every time. (Assuming you changed BeforeTriagSize to an int - if you need to hand it over as a pointer to some functions just use the address operator (&))
I have the following for my HashTable structure:
typedef char *HashKey;
typedef int HashValue;
typedef struct sHashElement {
HashKey key;
HashValue value;
} HashElement;
typedef struct sHashTable {
HashElement *items;
float loadFactor;
} HashTable;
I never really thought about it until now but I just realized there's two ways how I can use this:
Alternative 1:
void hashInitialize(HashTable *table, int tabSize) {
table->items = malloc(sizeof(HashElement) * tabSize);
if(!table->items) {
perror("malloc");
exit(1);
}
table->items[0].key = "AAA";
table->items[0].value = 45;
table->items[1].key = "BBB";
table->items[1].value = 82;
table->loadFactor = (float)2 / tabSize;
}
int main(void) {
HashTable t1;
int i;
hashInitialize(&t1, HASHSIZE);
for(i = 0; i < HASHSIZE - 1; i++) {
printf("PAIR(%d): %s, %d\n", i+1, t1.items[i].key, t1.items[i].value);
}
printf("LOAD FACTOR: %.2f\n", t1.loadFactor);
return 0;
}
Alternative 2:
void hashInitialize(HashTable **table, int tabSize) {
*table = malloc(sizeof(HashTable));
if(!*table) {
perror("malloc");
exit(1);
}
(*table)->items = malloc(sizeof(HashElement) * tabSize);
if(!(*table)->items) {
perror("malloc");
exit(1);
}
(*table)->items[0].key = "AAA";
(*table)->items[0].value = 45;
(*table)->items[1].key = "BBB";
(*table)->items[1].value = 82;
(*table)->loadFactor = (float)2 / tabSize;
}
int main(void) {
HashTable *t1 = NULL;
int i;
hashInitialize(&t1, HASHSIZE);
for(i = 0; i < HASHSIZE - 1; i++) {
printf("PAIR(%d): %s, %d\n", i+1, t1->items[i].key, t1->items[i].value);
}
printf("LOAD FACTOR: %.2f\n", t1->loadFactor);
return 0;
}
Question 1: They both seem to produce the same result. On main, both examples print the right key/value pair. So, what exactly is the different between them besides the syntax change (using (*table) instead of just table), the extra code to allocate memory for the HashTable structure and the declaration of HashTable pointer?
I've been writing a few data structures lately like stacks, linked lists, binary search trees and now hash tables. And for all of them, I've always used the alternative 2. But now I'm thinking if I could have used alternative 1 and simplify the code, removing most of the * and & that are all over the place.
But I'm asking this question to understand the differences between the two methods and if, and also why, I should use on over the other.
Question 2: As you can see in the structures code, HashKey is a pointer. However, I'm not using strdup nor malloc to allocate space for that string. How and why is this working? Is this OK to do? I've always used malloc or strdup where appropriate when handling dynamic strings or I would get lots of segmentation faults. But this code is not giving me any segmentation faults and I don't understand why and if I should do it like this.
First both solutions are perfectly right !
Alternative 1 :
Your HashTable is declared in the main, which means the struct is somewhere in the call stack. The struct will be destroy if you leave the scope. Note : In your case that can't happen because the declaration is in the main so the scope ends on process exit.
Alternative 2:
You've got a HashTable* (pointer) in the call stack so you need to allocate the memory for the struct. To do so you use malloc.
In both case your struct is correctly allocated. The main difference will be on performances. It's far more performant to allocate on the stack but you can't do dynamic allocation. To do so you need to use malloc.
So, some times, you have to use malloc but try to avoid mallocing a lot if you want to do a high performance application.
Is that clear enough? :)
In alternative 1, the caller would allocate table but your function would allocate the contents thereof, which is not always a good idea in terms of memory management. Alternative 2 keeps all allocations in the same place.
As answered previously, the differences between the two alternatives is memory management. In alternative 1 you expect the caller to allocate the memory for table prior to the call; whereas, in alternative 2 just a pointer declaration is required to give you a place to put the memory after you've created it.
To question 2, the simple answer is that you are assigning a constant to the string. According to the following site the assignment is set up at compile time, not runtime.
http://publications.gbdirect.co.uk/c_book/chapter6/initialization.html
for question 2:
(*table)->items[0].key = "AAA";
actually puts "AAA" in read only parts of memory and char *key points to it, contents pointed by key cannot be changed.
(*table)->items[0].key[0]='a' gives and error
Here you can find further discussion about it.
What is the difference between char s[] and char *s?
The only difference is where the memory comes from -- local variables are typically on the stack whereas mallocs typically come from the heap.