How to free pointer to an array of integers - c

I'm having problems figuring out how to free a pointer to an array of integers, my code is as follow:
int (*gameInfo)[2]; // [0] # of fouls || [1] # of players
gameInfo = (int *)malloc(size * sizeof(int*));
for (int i = 0; i < size; i++) {
memset(gameInfo[i], 0, 2 * sizeof(int));
}
I declare the pointer in the first line, initialize it in the second, and sets all values to 0 inside the for. It works fine.
After I load the new values, and use them I want to free the pointer. I do the following:
for (int i = 0; i < size; i++) {
free(gameInfo[i]);
}
free(gameInfo);
I'm trying to free the arrays first, and then free the pointer. I get a "has triggered a breakpoint" the first time it tries to execute "free(gameInfo[i])".
I've read that the array, since it doesn't have dynamic allocated memory, doesn't need to be free, but if I remove the for and just leave free(gameInfo); it gives the same error.
I've read this in a blog somewhere, so I'm not sure if it's trustworthy.
Thank you!

First, for your stated purposes, the declaration:
int (*gameInfo)[2]; // [0] # of fouls || [1] # of players
Could be:
int *gameInfo[2]; // [0] # of fouls || [1] # of players
Then, allocation for both elements of the array would look like this:
int size = 10; // for example
gameInfo[0] = malloc(size * sizeof(*gameInfo[0]));
gameInfo[1] = malloc(size * sizeof(*gameInfo[1]));
This essentially creates a quantity of space equivalent to that you would have with a 2D int array such as:
int gameInfo[2][10];
After use, free them:
free(gameInfo[0]);
free(gameInfo[1]);
A better option, as mentioned in the comments might be to create a struct:
typedef struct {
int fouls;
int players;
} GAME;
Usage can then include creating, using then freeing an array of games:
GAME *game;
game = calloc(10, sizeof(*game));
...
game[0].fouls = 3;
game[0].players = 2;
...
game[9].fouls = 6;
game[9].players = 3;
...
free(game);

To begin with, you allocate incorrectly. You are using an array pointer, so it should be set to point at an array, not to some fragmented pointer look-up table.
int (*gameInfo)[players]; // [0] # of fouls || [1] # of players
gameInfo = calloc(1, sizeof( int[fouls][players] ));
...
gameInfo[x][y] = something;
...
free(gameInfo);
That's it.
Not only did this turn the code much more readable, it also improves performance drastically.
Further study: Correctly allocating multi-dimensional arrays.

int(*gameInfo)[2];
gameInfo = (int*)malloc(4 * sizeof(int*));
for (int i = 0; i < 2; i++) {
memset(gameInfo[i], 0, 2 * sizeof(int));
}
free(gameInfo);
After some tests, I updated it. The reason lies on nonalignment of memset and malloc. Obviously you applied 2*sizeof(int) memory and memset 2 times of 2*sizeof(int), which is out of the range of 8 byte you applied. Apply 16 byte, in my system fixed the problem. And thanks for #Lundin for reminding me the problem.

Related

Can someone please explain this. It deals with malloc and global array in C

If I'm trying to create a global array to hold an arbitrary number of integers in this case 2 ints. How is it possible that I can assign more numbers to it if I only allocate enough space for just two integers.
int *globalarray;
int main(int argc, char *argv[]) {
int size = 2;
globalarray = malloc(size * sizeof(globalarray[0]));
// How is it possible to initialize this array pass
// the two location that I allocated.
for (size_t i = 0; i < 10; i++) {
globalarray[i] = i;
}
for (size_t i = 0; i < 10; i++) {
printf("%d ", globalarray[i]);
}
printf("%s\n", "");
int arrayLength = sizeof(*globalarray)/sizeof(globalarray[0]);
printf("Array Length: %d\n", arrayLength);
}
When I run this it gives me
0 1 2 3 4 5 6 7 8 9
Array Length: 1
So I wanted to know if someone could clarify this for me.
(1) Am I creating the global array correctly?
(2) Why is the array length 1? When I feel that it should be 2 since I malloced the pointer for 2.
And background info on why I want to know this is because I want to create a global array (shared array) so that threads can later access the array and change the values.
How is it possible to initialize this array pass the two location that I allocated.
Short answer: This is undefined behaviour and anything can happen, also the appearance that it worked.
Long answer: You can only initialize the memory you've allocated, it
doesn't matter that the variable is a global variable. C doesn't prevent you from
stepping out of bounds, but if you do, then you get undefined behaviour and anything can happen
(it can "work" but it also can crash immediately or it can crash later).
So if you know that you need 10 ints, then allocate memory for 10 int.
globalarray = malloc(10 * sizeof *globalarray);
if(globalarray == NULL)
{
// error handling
}
And if you later need more, let's say 15, then you can use realloc to increase
the memory allocation:
globalarray = malloc(10 * sizeof *globalarray);
if(globalarray == NULL)
{
// error handling
// do not contiue
}
....
// needs more space
int *tmp = realloc(globalarray, 15 * sizeof *globalarray);
if(tmp == NULL)
{
// error handling
// globalarray still points to the previously allocated
// memory
// do not continue
}
globalarray = tmp;
Am I creating the global array correctly?
Yes and no. It is syntactically correct, but semantically it is not, because you are
allocating space for only 2 ints, but it's clear from the next lines that
you need 10 ints.
Why is the array length 1? When I feel that it should be 2 since I malloced the pointer for 2.
That's because
sizeof(*globalarray)/sizeof(globalarray[0]);
only works with arrays, not pointers. Note also that you are using it wrong in
two ways:
The correct formula is sizeof(globalarray) / sizeof(globalarray[0])
This only works for arrays, not pointers (see below)
We sometimes use the term array as a visual representation when we do stuff
like
int *arr = malloc(size * sizeof *arr)
but arr (and globalarray) are not arrays,
they are pointers. sizeof returns the amount in bytes that the
expression/variable needs. In your case *globalarray has type int and
globalarray[0] has also type int. So you are doing sizeof(int)/sizeof(int)
which is obviously 1.
Like I said, this only works for arrays, for example, this is correct
// not that arr here is not an array
int arr[] = { 1, 2, 3, 4 };
size_t len = sizeof arr / sizeof arr[0]; // returns 4
but this is incorrect:
int *ptr = malloc(4 * sizeof *ptr);
size_t len = sizeof ptr / sizeof ptr[0]; // this is wrong
because sizeof ptr does not returns the total amount of allocated
bytes, it returns the amount of bytes that a pointer needs to be stored in memory. When you are dealing with
pointers, you have to have a separate variable that holds the size.
C does not prevent you from writing outside allocated memory. When coding in C it is of the utmost importance that you manage your memory properly.
For your second question, this is how you would want to allocate your buffer:
globalarray = malloc(sizeof(int) * size);
And if you are on an older version of C than c11:
globalarray = (int*) malloc(sizeof(int) * size);

A dynamic 1D array in C don't want to ingest each character of a file in each of his boxes

In C, I want to fill a dynamic array with each character of a file in each of his boxes.
But instead, when I print my array I have:
0 = []
1 = []
2 = []
3 = []
4 = []
5 = []
6 = []
7 = []
8 = []
9 = []
I have no compilation errors, but valgrind said that I have a:
Conditional jump or move depends on uninitialised value(s)
in my main at the printf.
That's strange, because even with an initialisation in my main:
array_valid_char = NULL;
valgrind keeps getting me that error.
And even if I change to:
printf("%d = [%d] \n", i, array_valid_char[i]);
the display is the same.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
int* f(char* name_file_in)
{
FILE *file_in;
int* array_valid_char = malloc(10 * sizeof(int*));
int read_char;
file_in = fopen(name_file_in,"rb");
if(file_in)
{
while ((read_char = fgetc(file_in)) != EOF)
{
*(array_valid_char++) = read_char;
}
}
if(file_in){fclose(file_in);}
return array_valid_char;
}
int main(int argc,char* argv[])
{
int *array_valid_char = malloc(10 * sizeof(int*));
array_valid_char = f(argv[1]);
for (int i = 0; i < 10; i++)
{
printf("%d = [%c] \n", i, array_valid_char[i]);
}
return(0);
}
What is wrong with my code?
You have to keep track of the beginning of the allocated memory which you didn't. (That original allocated chunks address should be returned ).
int* array_valid_char = malloc(10 * sizeof(int*));
int *st = array_valid_char ;
...
return st;
Also you have memory leak - you can omit the malloc in main().
Also you need to free the dynamically allocated memory when you are done working with it.
free(array_valid_char);
And also the memory allocation part would be
int* array_valid_char = malloc(10 * sizeof(int));
or
int* array_valid_char = malloc(10 * sizeof(*array_valid_char));
You want array of int.
Among other points check the return value of malloc and handle it properly.
The correct way to code would be to index into the allocated memory and check whether we are reaching limit of what we allocated - if it is so then reallocate.
Many of us confine ourselves with the thought that sizeof( *ptr)*10
is only good enough for the clear syntax etc but knowing that sizeof returns size_t when multiplied this with other value it is less likely to overflow as in opposed to writing the other way round(which was having int arithmetic) that's a benefit. (chux)
For example: sizeof(something)*int*int will do result in operation with size_t value which will less likely to overflow that int*int*sizeof(int). In second case int*int may overflow.(more likely)
There are some problems in your code:
With *(array_valid_char++), you move your pointer each time you pass on the loop. If you want to use this method, you need to keep a track on the beginning of your array with an other variable. You can also use an iterator array_valid_char[i] that starts at 0 and increments it at each loop turn.
In your main, you malloc your array int *array_valid_char = malloc(10 * sizeof(int*)); but you override it just after with array_valid_char = f(argv[1]);. If you malloc your array in a function and send it back with a return, the memory is still allocated.
In printf, %d is for display a number and %c is for display a character. In your case, you need to use %c. In the other case, you will see the ASCII value of your character.
By the way, you also use an int array to receive char array. It is not a problem now but for some optimisation, you can use char array to take less memory.
Also, don't forget to free the memory you have used when you don't use it anymore, it could be useful in bigger programs.

realloc can not access to the new size from other function

Im trying to increase the size of a **array with realloc which I have created with malloc.
I committed the **array to a function where I would like to increase the size.
Here is the part which increase the size:
imginf->height = imginf->height * 2;
imginf->width = imginf->width * 2;
array = realloc(array, imginf->height * sizeof(d*));
for(int i = 0; i < imginf->height; i++) {
array[i] = malloc(imginf->width * sizeof(d));
}
After that, I fill the array with two for loops. Everything works fine!
In the next function I try to save that array in a file. Here I use also two for loops.
With the first for loop I walk through the height and here I get the problem.
If the loop counter is (imginf->height /2) I ran out of the array. For the width everything’s works fine.
What went wrong? Especially, why could I fill the array?
Edit
Here the function definition for saving:
void Save(char * newname, inf imginf, d **array);
d is a struct with 3 unsigned chars.
Here the definition for the realloc function:
void reallocBig(inf *imginf, d **array);
Greetz.
C is a pass-by-value language. Your reallocBig function can't modify the value of the array in the caller. You need to change it to take a d *** parameter, and "fill in" that pointer in the function:
void reallocBig(inf *imginf, d ***array)
{
...
*array = realloc(...)
for (...)
(*array)[i] = ...
...
}
The C FAQ has a question about precisely your problem. You should also note that your current implementation leaks all of the previous entries in the array.

Is this code doing what I want it to do?

I want to create an integer pointer p, allocate memory for a 10-element array, and then fill each element with the value of 5. Here's my code:
//Allocate memory for a 10-element integer array.
int array[10];
int *p = (int *)malloc( sizeof(array) );
//Fill each element with the value of 5.
int i = 0;
printf("Size of array: %d\n", sizeof(array));
while (i < sizeof(array)){
*p = 5;
printf("Current value of array: %p\n", *p);
*p += sizeof(int);
i += sizeof(int);
}
I've added some print statements around this code, but I'm not sure if it's actually filling each element with the value of 5.
So, is my code working correctly? Thanks for your time.
First:
*p += sizeof(int);
This takes the contents of what p points to and adds the size of an integer to it. That doesn't make much sense. What you probably want is just:
p++;
This makes p point to the next object.
But the problem is that p contains your only copy of the pointer to the first object. So if you change its value, you won't be able to access the memory anymore because you won't have a pointer to it. (So you should save a copy of the original value returned from malloc somewhere. If nothing else, you'll eventually need it to pass to free.)
while (i < sizeof(array)){
This doesn't make sense. You don't want to loop a number of times equal to the number of bytes the array occupies.
Lastly, you don't need the array for anything. Just remove it and use:
int *p = malloc(10 * sizeof(int));
For C, don't cast the return value of malloc. It's not needed and can mask other problems such as failing to include the correct headers. For the while loop, just keep track of the number of elements in a separate variable.
Here's a more idiomatic way of doing things:
/* Just allocate the array into your pointer */
int arraySize = 10;
int *p = malloc(sizeof(int) * arraySize);
printf("Size of array: %d\n", arraySize);
/* Use a for loop to iterate over the array */
int i;
for (i = 0; i < arraySize; ++i)
{
p[i] = 5;
printf("Value of index %d in the array: %d\n", i, p[i]);
}
Note that you need to keep track of your array size separately, either in a variable (as I have done) or a macro (#define statement) or just with the integer literal. Using the integer literal is error-prone, however, because if you need to change the array size later, you need to change more lines of code.
sizeof of an array returns the number of bytes the array occupies, in bytes.
int *p = (int *)malloc( sizeof(array) );
If you call malloc, you must #include <stdlib.h>. Also, the cast is unnecessary and can introduce dangerous bugs, especially when paired with the missing malloc definition.
If you increment a pointer by one, you reach the next element of the pointer's type. Therefore, you should write the bottom part as:
for (int i = 0;i < sizeof(array) / sizeof(array[0]);i++){
*p = 5;
p++;
}
*p += sizeof(int);
should be
p += 1;
since the pointer is of type int *
also the array size should be calculated like this:
sizeof (array) / sizeof (array[0]);
and indeed, the array is not needed for your code.
Nope it isn't. The following code will however. You should read up on pointer arithmetic. p + 1 is the next integer (this is one of the reasons why pointers have types). Also remember if you change the value of p it will no longer point to the beginning of your memory.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define LEN 10
int main(void)
{
/* Allocate memory for a 10-element integer array. */
int array[LEN];
int i;
int *p;
int *tmp;
p = malloc(sizeof(array));
assert(p != NULL);
/* Fill each element with the value of 5. */
printf("Size of array: %d bytes\n", (int)sizeof(array));
for(i = 0, tmp = p; i < LEN; tmp++, i++) *tmp = 5;
for(i = 0, tmp = p; i < LEN; i++) printf("%d\n", tmp[i]);
free(p);
return EXIT_SUCCESS;
}
//Allocate memory for a 10-element integer array.
int array[10];
int *p = (int *)malloc( sizeof(array) );
At this point you have allocated twice as much memory -- space for ten integers in the array allocated on the stack, and space for ten integers allocated on the heap. In a "real" program that needed to allocate space for ten integers and stack allocation wasn't the right thing to do, the allocation would be done like this:
int *p = malloc(10 * sizeof(int));
Note that there is no need to cast the return value from malloc(3). I expect you forgot to include the <stdlib> header, which would have properly prototyped the function, and given you the correct output. (Without the prototype in the header, the C compiler assumes the function would return an int, and the cast makes it treat it as a pointer instead. The cast hasn't been necessary for twenty years.)
Furthermore, be vary wary of learning the habit sizeof(array). This will work in code where the array is allocated in the same block as the sizeof() keyword, but it will fail when used like this:
int foo(char bar[]) {
int length = sizeof(bar); /* BUG */
}
It'll look correct, but sizeof() will in fact see an char * instead of the full array. C's new Variable Length Array support is keen, but not to be mistaken with the arrays that know their size available in many other langauges.
//Fill each element with the value of 5.
int i = 0;
printf("Size of array: %d\n", sizeof(array));
while (i < sizeof(array)){
*p = 5;
*p += sizeof(int);
Aha! Someone else who has the same trouble with C pointers that I did! I presume you used to write mostly assembly code and had to increment your pointers yourself? :) The compiler knows the type of objects that p points to (int *p), so it'll properly move the pointer by the correct number of bytes if you just write p++. If you swap your code to using long or long long or float or double or long double or struct very_long_integers, the compiler will always do the right thing with p++.
i += sizeof(int);
}
While that's not wrong, it would certainly be more idiomatic to re-write the last loop a little:
for (i=0; i<array_length; i++)
p[i] = 5;
Of course, you'll have to store the array length into a variable or #define it, but it's easier to do this than rely on a sometimes-finicky calculation of the array length.
Update
After reading the other (excellent) answers, I realize I forgot to mention that since p is your only reference to the array, it'd be best to not update p without storing a copy of its value somewhere. My little 'idiomatic' rewrite side-steps the issue but doesn't point out why using subscription is more idiomatic than incrementing the pointer -- and this is one reason why the subscription is preferred. I also prefer the subscription because it is often far easier to reason about code where the base of an array doesn't change. (It Depends.)
//allocate an array of 10 elements on the stack
int array[10];
//allocate an array of 10 elements on the heap. p points at them
int *p = (int *)malloc( sizeof(array) );
// i equals 0
int i = 0;
//while i is less than 40
while (i < sizeof(array)){
//the first element of the dynamic array is five
*p = 5;
// the first element of the dynamic array is nine!
*p += sizeof(int);
// incrememnt i by 4
i += sizeof(int);
}
This sets the first element of the array to nine, 10 times. It looks like you want something more like:
//when you get something from malloc,
// make sure it's type is "____ * const" so
// you don't accidentally lose it
int * const p = (int *)malloc( 10*sizeof(int) );
for (int i=0; i<10; ++i)
p[i] = 5;
A ___ * const prevents you from changing p, so that it will always point to the data that was allocated. This means free(p); will always work. If you change p, you can't release the memory, and you get a memory leak.

Array of buffers in C programming?

I am trying to create an array of buffers. I need to store an integer into each buffer. I'm not quite sure how this should be done.
int BUFFER_LENGTH = 50; //the size of each buffer
int numberOfBuffers = 10; //number of buffers
int *pBuffers; //array of buffers
pBuffers = (int *) calloc (numberOfBuffers, sizeof(int)); //make array size of numberOfBuffers
int i;
for (i = 0; i < n; i++){ //initialize each buffer to zero.
&pBuffers[i] = 0x00;
}
What is it that I am doing wrong? This code isn't really working.
You might want to allocate enough space. Right there you only allocate enough space for 10 ints; looks like you want to allocate enough for 500. The simple way is int buffers[10][50]. But if you want to calloc, you have to calloc(BUFFER_LENGTH, sizeof(int)) numberOfBuffers times.
Also, calloc automatically clears the allocated memory, so no need to do that.
#define BUFFER_LENGTH 50 /* the size of each buffer */
#define BUFFERS 10 /* number of buffers */
int **pBuffers; /* array of buffers */
pBuffers = calloc (BUFFERS, sizeof(int *)); //make array of arrays
int i;
for (i = 0; i < BUFFERS; i++) {
pBuffers[i] = calloc(BUFFER_LENGTH, sizeof(int)); // make actual arrays
}
What you're creating with your sample is an array of integers. Instead, you'll want to create an array of integer arrays. The setup is similar, but you'll need to declare the variable as an int** and allocate each buffer individually.
int **ppBuffer = (int**) calloc(numberOfBuffers, sizeof(int*));
for(int i = 0; i < numberOfBuffers; ++i)
ppBuffer[i] = (int*) calloc(BUFFER_LENGTH, sizeof(int));
There's not much point in going through and initializing the arrays to 0 since calloc will already do that for you.
Of course, the easier thing if you know the size of each buffer is going to be the constants would be to put it on the stack (and change you're int sizes to constants):
int ppBuffer[numberOfBuffers][BUFFER_LENGTH] = { 0 };
I think what your asking is for an array of arrays, which isn't what your doing here in the code, rather you've created one array.
Try something like:
#define BUFFER_LENGTH 50
#define numberOfBuffers 10
int** pBuffers;
pBuffers = (int**) calloc(numberOfBuffers, sizeof(int*));
for (int i = 0; i < numberOfBuffers; i++)
pBuffers[i] = (int*) calloc(BUFFER_LENGTH, sizeof(int));
As others said calloc initializes to 0 for you so you don't need to repeat that work. You may need to define int i outside the for loop depending on the version of C you're using.
There are some other things that can be said about style and naming conventions but one step at a time :)
I am very rusty in C, but I think you should change
&pBuffers[i] = 0x00;
to
pBuffers[i] = 0x00;
(The [i] means you are already accessing the item in location i so there is no need to add the &.)
But I might be wrong :-(

Resources