In C can you have realloc inside realloc? For example, a struct inside a struct when you need to malloc both of them and realloc both of them. If yes can someone please provide a simple example?
Thank you in advance.
Your question is not dreadfully clear, but...
Yes, a given dynamically allocated structure (for example, an array of structures) can itself contain pointers to allocated data (such as various other arrays of allocated structures), and you can reallocate the various parts independently.
However, the system will not call realloc() for you while you are reallocating one of the structures; you would have to separately program the various resizing operations.
Example nested data structures:
struct line { char *info; size_t length; };
struct section { size_t num_lines; struct line *lines; };
You could allocate an array of sections, and reallocate that array when needed. Each section contains an array of lines, and each of those arrays of lines can be independently reallocated too.
Hence:
size_t num_sections = 0;
size_t max_sections = 0;
struct section *sections = 0;
if (num_sections == max_sections)
{
size_t new_max = (max_sections + 1) * 2;
struct section *new_sections;
if (sections == 0)
new_sections = malloc(new_max * sizeof(*new_sections));
else
new_sections = realloc(sections, new_max * sizeof(*new_sections));
if (new_sections == 0)
...out of memory error...
sections = new_sections;
max_sections = new_max;
}
struct section *section = §ions[num_sections++]; // Newly available section
section->num_lines = 0;
section->lines = 0;
return section;
(I'm assuming C99 - with variable declarations where I want them.)
A similar process applies for the array of lines within a section, except the section structure doesn't have separate values for the number of allocated lines and the number of lines actually in use. Each line also has its own allocated memory for the string of characters, of course...
Related
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.
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.
As part of an assignment, I have to deal with three structs. There is some larger table within a file, FileHeader, that is made up of SectionHeader structs. Hdr is made up of an array of these structs laid out in contiguous memory. As a result, I should be able to access the array by typecasting the location of the table in memory.
typedef struct {
unsigned int offset; // offset in bytes from start of file to section headers
unsigned short headers; // count of section headers in table
} FileHeader;
typedef struct {
unsigned int name;
unsigned int type;
} SectionHeader;
I am supposed to: Use the offset and headers fields from the FileHeader (hdr) to identify the location and length of the section header table. I have assumed the start of the file is &hdr.
So I did this, but it is giving me a seg-fault. What is the proper way to access this array?
int header_location = hdr.offset;
int header_length = hdr.headers;
SectionHeader *sec_hdrs = (SectionHeader *) &hdr + header_location;
SectionHeader sec_hdr;
for (int i = 0; i < header_length; i++) {
sec_hdr = sec_hdrs[i];
if (sec_hdr.type == SHT_SYMTAB) break;
}
Try this: ElfSectionHeader *sec_hdrs = (ElfSectionHeader *)((unsigned char *) &hdr + header_location);
Your orinal code &hdr + header_location would offset the pointer by sizeof(hdr) * header_location which is not your intention.
You declared sec_hdrs as a pointer to SectionHeader. It is not an array and it can't be indexed. Your compiler should raise a warning.
Try this:
SectionHeader hdrs[header_length]
int header_location = hdrs[0].offset;
int header_length = hdrs[0].headers;
SectionHeader *sec_hdrs = hdrs + header_location;
SectionHeader sec_hdr;
for (int i = 0; i < header_length; i++) {
sec_hdr = sec_hdrs[i];
if (sec_hdr.type == SHT_SYMTAB) break;
}
Here is a visualization of the memory with an initial offset followed by SectionHeader's placed in contiguous memory.
header_location | sizeof(SectionHeader)| sizeof(SectionHeader) | sizeof(SectionHeader)
vijairaj makes a very valid point about a possible bug in your code.
Your original code &hdr + header_location would offset the pointer by
sizeof(hdr) * header_location which is not your intention.
This is a valid diagnosis and you should investigate how pointer arithmetic works. We increment the address by the size of its type. Once you are sure that *sec_hdrs is pointing to the correct place, rerun your program. If the segfault persists, try my next piece of debugging advice.
Yes, on other questions here, I have seen that you might have to malloc first. But I do not understand why that is necessary if you have a pointer to the array if you know that it is in contiguous memory, and also how to do this.
Just because we know something is in contiguous memory does not mean it is safe from being overwritten or reused by our program. That is the point of malloc - to protect certain blocks of memory from being overwritten. If you access unallocated memory, you run the risk of accessing sensitive data, overwriting program-dependent data, or storing data that will get overwritten. This is why a segfault will occur and this is why you need to malloc.
Ensure that you malloc enough space:
malloc(header_location + header_length * sizeof(SectionHeader))
This line of code is saying, "Please allocate contiguous memory for one offset and n SectionHeader's". The malloc call will return a pointer to the start of that memory block (&hdr) and then you may access anything within that block of memory.
Perhaps include the code that is providing you with &hdr? Hope this is helpful!
i have a simple structure:
typedef struct {
int test;
} struct1_t;
typedef struct {
struct1_t** tests;
} struct2_t;
struct2_t *str
for(i=0;i<1000;i++) {
(str->tests)[i]=(test1_t *) malloc(sizeof(test1_t));
(str->tests)[i]->test = i;
}
How to know exist str->tests)[i] element on not ?
if (str->tests)[i] != NULL
call Segmentation failed :).
Simply put, you can't. There is no way to know the length of an array in C, you have to keep track of it manually as your array changes or grows.
C arrays are really just blocks of memory, so what you really
want to do as add a field to your structs that keeps track of how
much space has been allocated and make sure you initialize
everything to sane values. You also have to be careful when using
pointers of structs containing to pointers to pointers of structs,
since in your example you failed to properly allocate memory for
everything.
Try this:
typedef struct {
int test;
} test_t;
typedef struct {
test_t* tests; /* We only need a regular pointer here */
size_t numtests; /* This is so we know how many tests we allocated */
} mystruct_t;
/* .... Now skip to the actual usage: */
mystruct_t *str;
int i;
str = malloc(sizeof(mystruct_t)); /* Remember to allocate memory for
the container! */
str->numtests = 1000; /* Set our size inside the container and use it! */
/* Now to allocate an array of tests, we only need to allocate
a single chunk of memory whose size is the number of tests
multiplied by the size of each test: */
str->tests = malloc(sizeof(test_t)*str->numtests);
/* Now let's initialize each test: */
for (i=0; i<str->numtests; i++) { /* Notice we use str->numtests again! */
str->tests[i]->test = 1; /* Notice we don't need all the extra
parenthesese. This is due to the operator
precedence of [] and -> */
}
Now when you need to see if a test element exists, you can just see if the
index is within the size of the container:
if (i >= 0 && i < str->numtests) {
str->tests[i]->test = 2; /* This code only runs if the index would exist. */
}
But that means you have to take care to always initialize str->numtests to be
a sane value. For example, with no allocated tests:
mystruct_t *str = malloc(sizeof(mystruct_t));
/* Initialize the container to sane starting values! */
str->tests = NULL;
str->numtests = 0;
And that's how you know if something exists -- you keep track of it inside
the structures you define. That's because C code maps very directly to
assembly language, and C structs and arrays map very directly to bits and bytes
in computer memory, so if you want to maintain meta information like how
many elements are inside your array, you have to make room for that information
and store it yourself.
It is pretty fundamental that you can't do it this way in C. Your struct2_t would need an extra field such as int no_of_tests, which you would update.
In fact to do what your trying to do there, you also need 2 mallocs -
struct2_t str;
str.tests = malloc( 1000 * sizeof(int) );
str.no_of_tests = 1000;
for(i=0;i<1000;i++) {
str.tests[i] = malloc( sizeof(struct1_t) );
str.tests[1]->test = i;
}
There is nothing in the language to do this for you, you need to keep track yourself. A common solution is to make the last pointer in an arbitrary-size array of pointers be a NULL pointer, so you know to stop looping when you hit NULL.
If your compiler supports _msize you can find out the size that you allocated. For example:
if (i < _msize((str->tests)/sizeof(test1_t))
then i is valid and points to an element of the allocated array
I am writing a light weight serialization function and need to include two variable sized arrays within this.
How should I track the size of each?
How should I define the struct?
Am I going about this all wrong?
EDIT: the result must be a contiguous block of memory
This resolves to something like
typedef struct
{
size_t arr_size_1, arr_size_2;
char arr_1[0/*arr_size_1 + arr_size_2*/];
} ...;
The size(s) should be in the front of the dynamic sized data, so that it doesn't move when expanding your array.
You cannot have 2 unknown sized arrays in your struct, so you must collapse them into one and then access the data relative from the first pointer.
typedef struct MyStruct_s
{
int variable_one_size;
void* variable_one_buf;
int variable_two_size;
void* variable_two_buf;
} MyStruct;
MyStruct* CreateMyStruct (int size_one, int size_two)
{
MyStruct* s = (MyStruct*)malloc (sizeof (MyStruct));
s->variable_one_size = size_one;
s->variable_one_buf = malloc (size_one);
s->variable_two_size = size_two;
s->variable_two_buf = malloc (size_two);
}
void FreeMyStruct (MyStruct* s)
{
free (s->variable_one_buf);
free (s->variable_two_buf);
free (s);
}
Since the data should be continuous in memory it is necessary to malloc a chunk of memory of the right size and manage it's contents more or less manually. You probably best create a struct that contains the "static" information and related management functions that do the memory management and give access to the "dynamic" members of the struct:
typedef struct _serial {
size_t sz_a;
size_t sz_b;
char data[1]; // "dummy" array as pointer to space at end of the struct
} serial;
serial* malloc_serial(size_t a, size_t b) {
serial *result;
// malloc more memory than just sizeof(serial), so that there
// is enough space "in" the data member for both of the variable arrays
result = malloc(sizeof(serial) - 1 + a + b);
if (result) {
result->sz_a = a;
result->sz_b = b;
}
return result;
}
// access the "arrays" in the struct:
char* access_a(serial *s) {
return &s->data[0];
}
char* access_b(serial *s) {
return &s->data[s->sz_a];
}
Then you could do things like this:
serial *s = ...;
memcpy(access_a(s), "hallo", 6);
access_a(s)[1] = 'e';
Also note that you can't just assign one serial to another one, you need to make sure that the sizes are compatible and copy the data manually.
In order to serialize variably-sized data, you have to have a boundary tag of some sort. The boundary tag can be either a size written right before the data, or it can be a special value that is not allowed to appear in the data stream and is written right after the data.
Which you choose depends on how much data you are storing, and if you are optimizing for size in the output stream. It is often easier to store a size before-hand, because you know how big to make the receiving buffer. If you don't then you have to gradually resize your buffer on load.
In some ways, I'd do things like Dan Olson. However:
1) I'd create the final struct by having two instances of a simpler struct that has just one variable array.
2) I'd declare the array with byte* and use size_t for its length.
Having said this, I'm still not entirely clear on what you're trying to do.
edit
If you want it contiguous in memory, just define a struct with two lengths. Then allocate a block big enough for both blocks that you want to pass, plus the struct itself. Set the two lengths and copy the two blocks immediately after. I think it should be clear how the lengths suffice to make the struct self-describing.