C - Self-referencing structure and realloc - c

I've got a problem with calling realloc on self-referencing structure. When I run this program, I get error *** Error in ...: realloc(): invalid next size: 0x0000000000602160 ***. I suppose the problem is related to the last line, because program runs without any problem if I comment it.
This is the smallest (not) working piece of code:
#include <string.h>
#include <stdlib.h>
typedef struct structure {
int connections;
struct structure *links;
} structure;
int main(int argc, char *argv[]) {
int struct_count;
int i, from, to, offset;
structure *structs;
struct_count = 2;
structs = malloc(sizeof(structure) * struct_count);
memset(structs, 0, sizeof(structure) * struct_count);
for(i = 0; i < struct_count; i++) {
structs[i].links = malloc(1);
structs[i].connections = 0;
}
for(i = 0; i < 100; i++) {
from = 0;
to = 1;
offset = structs[from].connections++;
structs[from].links = realloc(structs[from].links, sizeof(int) * (offset + 1));
structs[from].links[offset] = structs[to]; // This is the problematic line - why?
}
}
And my question: what's wrong in that code?

The problem is the first time you allocate it, it's not enough. To allocate n elements of a given type you can use
structs[i].links = malloc(n * sizeof(*structs[i].links));
and the same goes wit realloc() you also need to make sure that realloc() doesn't return NULL, suppose that after allocating space for n structures with the line above you want to resize to store n + 1 instances, then
struct structure *links;
links = realloc(structs[i].links, (n + 1) * sizeof(*links));
if (links == NULL)
{
/* Depending on the way your program is designed */
probably_free_links(&structs[i].links);
/* ^ make it `NULL' inside */
allocation_failure_do_something_about_it_but_do_not_continue();
}
structs[i].links = links;
you can make structs[i].links = NULL; initially and realloc() will behave as malloc() the first time.
Write your programs as if all errors are possible, and do something about them don't just let your program invoke undefined behavior and make it a mistery to you and your program users.

If You will increase the Blueprint of structure and decrease the size of loop it will run perfectly..
**For Example:-**without manipulating run your program just decrease the loop condition from 100 to 2. It will run perfectly.
If you want to increase loop size you have to increase the size of structure.

Related

ERROR "realloc(): invalid next size" when allocating memory to const char*** variable

I have a function
populateAvailableExtensions(const char** gAvailableExtensions[], int gCounter)
which take a pointer to an array of strings and the number of elements in the array as parameters.
I allocate initial memory to that array using malloc(0). Specs say that it will either return a null pointer or a unique pointer that can be passed to free().
int currentAvailableExtensionCount = gCounter;
This variable will store number of string in gAvailableExtensions.
Inside this for loop
for (int i = 0; i < availableExtensionCount; ++i)
I have this piece of code
size_t sizeOfAvailableExtensionName =
sizeof(availableExtensionProperties[i].name);
reallocStatus = realloc(*gAvailableExtensions, sizeOfAvailableExtensionName);
memcpy(&(*gAvailableExtensions)[currentAvailableExtensionCount],
&availableExtensionProperties[i].name,
sizeOfAvailableExtensionName);
++currentAvailableExtensionCount;
where
availableExtensionProperties[i].name
returns a string.
This is how that struct is defined
typedef struct Stuff {
char name[MAX_POSSIBLE_NAME];
...
...
} Stuff;
realloc(*gAvailableExtensions, sizeOfAvailableExtensionName);
should add memory of size sizeOfAvailableExtensionName to *gAvailableExtensions de-referenced array.
memcpy(&(*gAvailableExtensions)[currentAvailableExtensionCount],
&availableExtensionProperties[i].name,
sizeOfAvailableExtensionName);
should copy the string (this sizeOfAvailableExtensionName much memory) from
&availableExtensionPropterties[i].name
address to
&(*gAvailableExtensions)[currentAvailableExtensionCount]
address.
But I don't think the code does what I think it should because I'm getting this error
realloc(): invalid next size
Aborted
(core dumped) ./Executable
EDIT: Full code
uint32_t populateAvailableExtensions(const char** gAvailableExtensions[], int gCounter) {
int currentAvailableExtensionCount = gCounter;
void* reallocStatus;
uint32_t availableExtensionCount = 0;
vkEnumerateInstanceExtensionProperties(
VK_NULL_HANDLE, &availableExtensionCount, VK_NULL_HANDLE);
VkExtensionProperties availableExtensionProperties[availableExtensionCount];
vkEnumerateInstanceExtensionProperties(
VK_NULL_HANDLE, &availableExtensionCount, availableExtensionProperties);
for (int i = 0; i < availableExtensionCount; ++i) {
size_t sizeOfAvailableExtensionName =
sizeof(availableExtensionProperties[i].extensionName);
reallocStatus = realloc(*gAvailableExtensions, sizeOfAvailableExtensionName);
memcpy(&(*gAvailableExtensions)[currentAvailableExtensionCount],
availableExtensionProperties[i].extensionName,
sizeOfAvailableExtensionName);
++currentAvailableExtensionCount;
}
return currentAvailableExtensionCount;
}
This is how an external function calls on that one,
uint32_t availableExtensionCount = 0;
availableExtensions = malloc(0);
availableExtensionCount = populateAvailableExtensions(&availableExtensions);
and
const char** availableExtensions;
is declared in header file.
EDIT 2: Updated the code, now gCounter holds the number of elements in gAvailableExtensions
This loop is totally messy:
for (int i = 0; i < availableExtensionCount; ++i) {
size_t sizeOfAvailableExtensionName =
sizeof(availableExtensionProperties[i].extensionName);
reallocStatus = realloc(*gAvailableExtensions, sizeOfAvailableExtensionName);
memcpy(&(*gAvailableExtensions)[currentAvailableExtensionCount],
availableExtensionProperties[i].extensionName,
sizeOfAvailableExtensionName);
++currentAvailableExtensionCount;
}
I assume the only lines that does what you expect them to do, are the lines for (int i = 0; i < availableExtensionCount; ++i) and ++currentAvailableExtensionCount;
First, the typical way to use realloc is like this:
foo *new_p = realloc(p, new_size);
if (!new_p)
handle_error();
else
p = new_p;
The point is that realloc will not update the value of p if a reallocation happens. It is your duty to update 'p'. In your case you never update *gAvailableExtensions. I also suspect that you don't calculate sizeOfAvailableExtensionCount correctly. The operator sizeof always return a compile time constant, so the realloc doesn't actuall make any sense.
The memcpy doesn't actally make any sense either, since you are copying the string into the memory of a pointer array (probably with an additional buffer overflow).
You said that *gAvailableExtensions is a pointer to an array of pointers to strings.
That means that you have to realloc the buffer to hold the correct number of pointers, and malloc memory for each string you want to store.
For this example, I assume that .extensionName is of type char * or char[XXX]:
// Calculate new size of pointer array
// TODO: Check for overflow
size_t new_array_size =
(currentAvailableExtensionCount + availableExtensionCount) * sizeof(*gAvailableExtensions);
char **tmp_ptr = realloc(*gAvailableExtensions, new_array_size);
if (!tmp_ptr)
{
//TODO: Handle error;
return currentAvailableExtensionCount;
}
*gAvailableExtensions = tmp_ptr;
// Add strings to array
for (int i = 0; i < availableExtensionCount; ++i)
{
size_t length = strlen(availableExtensionProperties[i].extensionName);
// Allocate space for new string
char *new_s = malloc(length + 1);
if (!new_s)
{
//TODO: Handle error;
return currentAvailableExtensionCount;
}
// Copy string
memcpy (new_s, availableExtensionProperties[i].extensionName, length + 1);
// Insert string in array
(*gAvailableExtensions)[currentAvailableExtensionCount] = new_s;
++currentAvailableExtensionCount;
}
If you can guarantee that the lifetime of availableExtensionProperties[i].extensionName is longer than *gAvailableExtensions, you can simplify this a little bit by dropping malloc and memcpy in the loop, and do:
char *new_s = availableExtensionProperties[i].extensionName;
(*gAvailableExtensions)[currentAvailableExtensionCount] = new_s;
Some harsh words at the end: It seems like you have the "Infinite number of Monkeys" approach to programming, just hitting the keyboard until it works.
Such programs will just only give the illusion of working. They will break in spectacular ways sooner or later.
Programming is not a guessing game. You have to understand every piece of code you write before you move to the next one.
int currentAvailableExtensionCount =
sizeof(*gAvailableExtensions) / sizeof(**gAvailableExtensions) - 1;
is just a obfuscated way of saying
int currentAvailableExtensionCount = 0;
I stopped reading after that, because i assume that is not what you intend to write.
Pointers in c doesn't know how many elements there are in the sequence they are pointing at. They only know the size of a single element.
In your case *gAvailableExtensions is of type of char ** and **gAvailableExtensions is of type char *. Both are pointers and have the same size on a typical desktop system. So on a 64 bit desktop system the expression turns into
8/8 - 1, which equals zero.
Unless you fix this bug, or clarify that you actually want the value to always be zero, the rest of the code does not make any sense.

Why can't I realloc an array that was fully initialized?

Have a look at the piece of code below. When I create an array by mallocating space for it I can always resize the array without loss of data. But when I create an array by fully initializing it with int test2[] = {3}; I am unable to realloc. Why is that? This is just a silly example but it presents the problem I am facing well.
I tried referencing test2 in different ways (*, &, **, etc) but at some point I found myself just hoping to magically find the solution without knowing what I was doing anymore.
I have been googling a lot but I cannot seem to find a proper explanation for this or solution that works.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int *test1 = malloc(1 * sizeof(int));
test1[0] = 1;
test1 = realloc(test1, 2 * sizeof(int));
test1[1] = 2;
for(int i = 0; i < 2; i++)
{
printf("%d\n", test1[i]);
}
int test2[] = {3};
test2 = realloc(test2, 2 * sizeof(int));
test2[1] = 4;
for(int i = 0; i < 2; i++)
{
printf("%d\n", test2[i]);
}
}
Output:
test.c: In function 'main':
test.c:17:8: error: assignment to expression with array type
test2 = realloc(test2, 2 * sizeof(int));
When I remove the code after the first for loop, the program compiles and executes nicely as it should.
The declaration int test2[] = {3}; does not create memory that can be later either freed or re-allocated! Rather, it defines an array of fixed length, most likely 'created' on the stack.
A call to malloc, on the other hand, allocates the requested amount of memory from the heap (essentially, a large pool of memory available to your running program); this memory 'chunk' can later be re-sized with realloc and must be released (when you're done with it) by calling free.

Access violation error when trying to free an array

I'm currently working on structures for a personnal project. I'm trying to use dynamically-allocated bidimensionnal arrays, and then free the space they're taking. An error occurs when I try to free the allocated space.
I was able to narrow down the source of the issue down to the function I had set up to destroy my structures, but wasn't able to pinpoint the cause of the error within. More concerning is the fact that the error, an access violation, only triggers half of the time.
I've included the functions below, with a few comments. I'm sorry if I'm including too much code here, but I'm geniunely lost at words and do feel like the way I initialize the structures may have an impact on whether I'm destroying them correctly.
#include <stdio.h>
#include <stdlib.h>
typedef struct f_part f_part;
typedef struct field field;
//these are the structures I used:
//part of a field: includes a character and a color
struct f_part
{
char caractere;
short int color;
};
//field: points to a bidimensionnal array of f_part, and remember its size
struct field
{
int fsize_x;
int fsize_y;
f_part **fbody;
};
field* fieldInitialize(const int size_x, const int size_y) //this function seems to work correctly, I've mostly added it as an indicator
{
field* terrain = malloc(sizeof(*terrain));
if (terrain == NULL)
printf("fail1");
terrain->fsize_x = size_x;
terrain->fsize_y = size_y;
f_part* ptrToFPart = NULL;
terrain->fbody = malloc(sizeof(ptrToFPart) * size_x); //this is where I allocate the space for an array of pointers
if (terrain->fbody == NULL)
printf("fail2");
int i,j;
for (i = 0 ; i < size_x ; i++)
{
terrain->fbody[i] = malloc(sizeof(f_part) * size_y);
for (j = 0 ; j < size_y ; j++)
{
terrain->fbody[i][j].caractere = 'a';
terrain->fbody[i][j].color = 0;
}
}
terrain->fsize_x = size_x;
terrain->fsize_y = size_y;
return terrain;
}
void fieldDestroy(field* terrain) //this is the function that is supposed to destroy the object and free the memory, and fails
{
int i;
for (i = 0 ; i < terrain->fsize_x ; i++)
{
free(terrain->fbody[i]); //this part always goes well
}
printf("flag 1\n");
free(terrain->fbody); //this is where the access violation happens, when it does
printf("flag 2\n");
free(terrain); //this part goes well too
printf("flag 3\n");
}
int main()
{
field* testField = fieldInitialize(5, 5);
fieldDestroy(testField); //This is the function that fails. Sometimes.
return 0;
}
The error systematically happens on that second-to-last line, when I try to free the space allocated for the array of pointers. Except it doesn't always happen! Sometimes, I can free terrain->fbody, and everything goes well, but other times, I can't free the space.
The error I get is 0xC0000005, which apparently translates to "access violation". Which I understand would be common when dealing with dynamic memory allocation, but then why do I seem to get the error only half of the time?
Edit : Okay, so I've edited a bit of the code. Interestingly enough, while my Windows 10 would fail between flags 1 and 2, my Windows 7 fails between flags 2 and 3, and returns too a 0xC0000005 error. But again, only occasionally.
In C, you must precede structure names with struct. So your functions should be declared:
struct field* fieldInitialize( ... )
and your allocations should be
struct field* terrain = malloc(sizeof(struct field));
You could also define these structures as types:
typedef struct
{
int fsize_x;
int fsize_y;
struct f_part **fbody;
} field;

How to declare an array with an arbitrary size

Ok, this is a C programming homework question. But I'm truly stuck.
I ask the user to input words, and then I insert the input into an array, but I can't have any control over the number of words the user types.
I guess what I'm asking is how do you declare a an array in C without declaring its length and without asking the user what the length should be.
I know this has something to do with malloc, but if you could give me some examples of how to do this, I would really appreciate it.
You can malloc a block of memory large enough to hold a certain number of array items.
Then, before you exceed that number, you can use realloc to make the memory block bigger.
Here's a bit of C code that shows this in action, reallocating an integer array whenever it's too small to hold the next integer.
#include <stdio.h>
#include <stdlib.h>
int main (void) {
int *xyzzy = NULL; // Initially NULL so first realloc is a malloc.
int currsz = 0; // Current capacity.
int i;
// Add ten integers.
for (i = 0; i < 10; i++) {
// If this one will exceed capacity.
if (i >= currsz) {
// Increase capacity by four and re-allocate.
currsz += 4;
xyzzy = realloc (xyzzy, sizeof(int) * currsz);
// Should really check for failure here.
}
// Store number.
xyzzy[i] = 100 + i;
}
// Output capacity and values.
printf ("CurrSz = %d, values =", currsz);
for (i = 0; i < 10; i++) {
printf (" %d", xyzzy[i]);
}
printf ("\n");
return 0;
}
You can realloc it every time like:
int size = 0;
char **array = malloc(0);
while(/* something */)
{
char *string = // get input
size++;
array = realloc(array, size * sizeof(char*));
array[size - 1] = string;
}
Or in chunks if you care about speed.
Yes, you want malloc. Checkout this tut.
http://www.cprogramming.com/tutorial/dynamic_memory_allocation.html
This site is good in general for learning.
Here is an example of using realloc, it is basically exactly what you are asking to do.
http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/
0) obviously you will need multiple buffers, so you will need a list like structure: perhaps a record with char array 100 chars and a pointer to next structure
1) You need to capture the words char by char and store them in your buffer
2) once the buffer is full you allocate another record, chain it with the previous one and keep going until you are out of mem or the process is over.
That should be better performance than realloc function. I believe malloc is trying to give contious block of memory. Therefore the list like structure will be faster and work better.

Freeing a dynamically allocated 2D structure

I've dynamically allocated a structure, conceptually very similar to a matrix, to hold a set of strings. I've encountered a problem while trying to free the memory. My code looks like this:
# include <stdio.h>
# include <string.h>
# include <malloc.h>
# define SIZE 2
typedef struct fork{
char** dataPointersArray;
char* dataArray;
}fork;
int main(int argc, char* argv[]){
fork forkDS;
int i;
char* dataArrayPtr;
unsigned char data[255] = "some data"; /* this is actually a function's output */
int PtrIndex;
/* allocate memory for the arrays */
forkDS.dataPointersArray = (char**) calloc(SIZE ,sizeof(char*));
if(forkDS.dataPointersArray == NULL){
printf("couldn't allocate memory \n");
}
forkDS.dataArray = (char*) calloc(SIZE, 255);
if( forkDS.dataArray == NULL){
free(forkDS.dataPointersArray);
printf("couldn't allocate memory \n");
}
dataArrayPtr = forkDS.dataArray;
for(i = 0; i < SIZE; i++){
/* update the dataPointers Array */
forkDS.dataPointersArray[i] = dataArrayPtr;
/* copy data into data array */
memcpy(dataArrayPtr,data,20);
dataArrayPtr[255] = '\0';
/* update the pointer of the data array */
dataArrayPtr = dataArrayPtr + 256;
}
for (PtrIndex = 0; PtrIndex < 2; PtrIndex++) {
if (*(forkDS.dataPointersArray + PtrIndex) != NULL) {
*(forkDS.dataPointersArray + PtrIndex) = NULL;
}
}
/* DEBUG comment - this 2 lines works */
free(forkDS.dataArray);
forkDS.dataArray = NULL;
/* DEBUG comment - the next line fails */
free(forkDS.dataPointersArray);
forkDS.dataPointersArray = NULL;
return 0;
}
So the structure actually contains 2 arrays, one of pointers to strings, and the other one contains the strings aligned one after the other, separated by a terminating \0.
The code works fine, and the for loop in the end works as well. The first call to free also works. The problem is that the last call to free fails.
Although trying to search all possible data on the issue, all the examples I've found regarded the case where the second array, which holds the strings, is allocated step by step in a for loop, and freed afterwards in a for loop as well.
I wanted to avoid using dynamic allocation in a loop, and therefore my code looks different.
Does anyone know what the problem is?
======================================================================================
Thanks a lot to all of you who answered me. Eventually, the bug was solved. The problem was that the dataPointersArray was filled with more than SIZE elements in some other piece of code, which seemed innocent at first, and actually caused the free call to fail.
Thanks again for the comments!
Shachar
You are allocating SIZE*255 bytes, but using SIZE * 256 bytes:
forkDS.dataArray = (char*) calloc(SIZE, 255);
dataArrayPtr = forkDS.dataArray;
//SIZE TIMES loop:
dataArrayPtr = dataArrayPtr + 256;
So when you are NULLing the pointers, you probably overwrite control data placed past the end of the array by malloc that free is looking for.
You allocated the space for an array consisting of SIZE lines with 255 characters each. The highest index on each line therefore is 254 = 255 - 1. As you write the \0 character, you write it at the beginning of the next line. After the last iteration, you would be off by SIZE bytes.
Just another detail: If any of the memory allocations failed, the program would only print its error messages, but it won't stop causing a SEGFAULT later.

Resources