Why does this show a warning for dereferencing nullptr in C
Level1Tilemap->Map = (int*)((malloc(Level1Columns * sizeof(int))));
for (int i = 0; i < Level1Columns; i++)
{
Level1Tilemap->Map[i] = malloc(Level1Rows * sizeof(int));
for (int j = 0; j < Level1Rows; j++)
{
Level1Tilemap->Map[i][j] = Level1MapStaticArray[i][j];
}
}
I am using malloc to create a 2D array of ints
But the editor shows warning and Level1Tilemap->Map has the memory address of nullptr
And the defination int** Map;
You might have meant to use a pointer-to-pointer, in which case sizeof(int) should have been sizeof(int*). However, don't do that, it's obscure and slow, for no good reason.
Instead do
size_t size = sizeof(int[Level1Columns][Level1Rows]);
int (*something)[Level1Rows] = malloc(size);
if(something == NULL) { /* error handling */ }
memcpy(something, Level1MapStaticArray, size);
...
free(something);
Apart from reducing code complexity, this will significantly outperform the code you have currently.
// map is an array of (int*), and the length is column
int** map = (int**) malloc(column * sizeof(int*));
for (int i = 0; i < column; ++i) {
// map[i] is an array of int, and the length is row
map[i] = malloc(row * sizeof(int*));
for (int j = 0; j < row; ++j)
map[i][j] = 0;
}
Related
I have a 2 dimensional array of pointers:
typedef struct Cell{
Position p;
unsigned int value;
} Cell;
typedef struct Position{
unsigned int x;
unsigned int y;
} Position;
int size = 4;
Cell ***cells = malloc(sizeof(Cell**) * size);
int i,j;
for(i = 0; i < size; i++){
cells[i] = malloc(sizeof(Cell*) * size);
for(j = 0; j < size; j++){
cells[i][j] = malloc(sizeof(Cell));
}
}
What I want to do now is fill this array with pointers to cells, and initialize these cells to contain the value 0 like this:
for(i = 0; i < size; i++){
for(j = 0; j < size; j++){
Position p = {i,j};
Cell c = {p, 0};
cells[i][j] = &c; //This doesn't work
}
}
As you can already tell, writing the address of c into the pointer cells[i][j] is less than ideal, since every pointer now points to the same address. However I don't know how to fill this array with pointers pointing to individual addresses.
I tried something like this:
cells[i][j]->value = 0;
which of course also doesn't work. Can anyone give me a hint on how I can solve my problem?
I'm not sure why you say cells[i][j]->value = 0; doesn't work, I believe it should.
This should work to set all the members.
Cell ***cells = malloc(sizeof(Cell**) * size);
for(i = 0; i < size; i++){
cells[i] = malloc(sizeof(Cell*) * size);
for(j = 0; j < size; j++){
cells[i][j] = malloc(sizeof(Cell));
cells[i][j]->p.x = i;
cells[i][j]->p.y = j;
cells[i][j]->value = 0;
}
}
Additional:
for(i = 0; i < size; i++){
for(j = 0; j < size; j++){
Position p = {i,j};
Cell c = {p, 0};
cells[i][j] = &c; //This doesn't work
}
// to this line, 'c' & 'p' will be freed since it was allocated on stack not heap.
// 'c' & 'p' will be freed when program gets out of 2nd for loop, so either you can
// use memcpy to copy 'c' into cells[i][j] or use malloc to allocate 'c' and 'p'
}
You've already gotten your answer but I see no obvious reason to do that many allocations unless sizeof(Cell) * size * size is large enough to make a single allocation fail (but allocating smaller parts doesn't). I suggest doing one allocation only which gives a few benefits. In no particular order:
Faster allocation in most cases.
Faster access to the elements that will be tightly packed and therefore be more cache friendly.
Easier memory management - there is only one pointer to check and free.
Less total memory allocated than when allocating memory for a lot of pointers.
Example 1 - Make cells a pointer to the first of size number of elements of Cell[size].
// one allocation:
Cell (*cells)[size] = malloc( size * sizeof *cells );
if(cells == NULL) exit(1); // check for allocation failure
for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
cells[i][j].p.y = i;
cells[i][j].p.x = j;
cells[i][j].value = 0;
}
}
Example 2 - Make cells a pointer to a single Cell[size][size]:
// one allocation:
Cell (*cells)[size][size] = malloc( sizeof *cells );
if(cells == NULL) exit(1); // check for allocation failure
for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
(*cells)[i][j].p.y = i;
(*cells)[i][j].p.x = j;
(*cells)[i][j].value = 0;
}
}
I am a bit of a beginner in C language. I was trying out a task of dynamically reallocating memory as the input comes through(although for this test I am doing a normal task, later will try to scale it up). the issue I am facing is I am unable to access the memory while writing into it. Can anyone please help me understand where I am going wrong in this code. thanks in advance.
code:
#include<stdio.h>
#include<stdlib.h>
struct ai {
int* a;
char* b;
};
int main()
{
struct ai *test;
test = (struct ai*) malloc(sizeof(struct ai));
test[0].a = (int*)malloc(sizeof(int));
test[0].b = (char*)malloc(sizeof(char));
/// storing info
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++)
{
test[i].a[j] = j;
test[i].b[j] = 65 + j;
test[i].a = (int *) realloc(test[i].a, (j + 2) * sizeof(int));
test[i].b = (char*) realloc(test[i].b, (j + 2) * sizeof(char));
}
test = (struct ai*)realloc(test, (i + 2) * sizeof(struct ai));
}
// printing the block out
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%d , %c\n", test[i].a[j], test[i].b[j]);
}
}
return 0;
} ```
You have missing initialization of your pointers and some other issues...
int main()
{
struct ai *test;
test = (struct ai*) malloc(sizeof(struct ai));
test[0].a = (int*)malloc(sizeof(int));
test[0].b = (char*)malloc(sizeof(char));
In C you should not cast the result of malloc. In best case it is useless. In worst case it hides real problems.
/// storing info
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++)
{
test[i].a[j] = j;
test[i].b[j] = 65 + j;
Here comes the reason for your segmentation fault:
You do not have any memory reserved for a and b except for the first element test[0]. All other array elements test[i] do not contain any useful data. Dereferencing these pointers is undefined behaviour.
You must allocate memory for each field after you enlarged your array.
test[i].a = (int *) realloc(test[i].a, (j + 2) * sizeof(int));
test[i].b = (char*) realloc(test[i].b, (j + 2) * sizeof(char));
You should never assign the return value of realloc to the same variable that you passed into the function. In case of an error you will get NULL return value and then your initiali pointer is lost.
Also here: don't cast for realloc as well.
}
test = (struct ai*)realloc(test, (i + 2) * sizeof(struct ai));
Same here: Don't assign to same variable and don't cast the result of realloc.
Finally: Here goes the missing part:
test[i+1].a = malloc(sizeof(*test[0].a));
test[i+1].b = malloc(sizeof(*test[0].b));
}
Of course you should check all return values for error results.
Not related to the segmentation fault, but still worth to fix:
You increment the size of each array after you used the last element.
This prepares the new element for being filled in next iteration of the loops. But in case of the last iteration it allocated an unused element for both the intern pointers a and b as well as the outer array test.
You will have some unused elements:
test[0].a[4]
test[0].b[4]
test[1].a[4]
test[1].b[4]
test[2].a[0]
test[2].b[0]
An improved solution could look like this (not tested)
I start with each pointer being NULL and use realloc right before the new element is used to avoid the extra elements.
int main(void)
{
struct ai *test = NULL
void *tmp;
// storing info
for (int i = 0; i < 2; i++)
{
tmp = realloc(test, (i+1) * sizeof(*test))
if (tmp == NULL)
exit(1);
test = tmp;
test[i].a = NULL;
test[i].b = NULL;
for (int j = 0; j < 4; j++)
{
tmp = realloc(test[i].a, (j+1) * sizeof(test[i].a[0]));
if (tmp == NULL)
exit(1);
test[i].a = tmp;
tmp = realloc(test[i].b, (j+1) * sizeof(test[i].b[0]));
if (tmp == NULL)
exit(1);
test[i].b = tmp;
test[i].a[j] = j;
test[i].b[j] = 65 + j;
}
}
// printing the block out
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%d , %c\n", test[i].a[j], test[i].b[j]);
}
}
return 0;
}
I'm trying to multiply two dynamic matrices by passing them through a function. I'm getting a segmentation fault during the multiplication.
The matrices are being passed through a function. The items in the arguments are correct because I had to use them for a different operation in this project. I have a feeling that I messed up with the pointers, but i'm pretty new to C and i'm not sure where I messed up.
double** multiplyMatrices(
double** a,
const uint32_t a_rows,
const uint32_t a_cols,
double** b,
const uint32_t b_cols){
uint32_t i = 0;
uint32_t j = 0;
uint32_t k = 0;
double** c;
//allocate memory to matrix c
c = (double **)malloc(sizeof(double *) * a_rows);
for (i = 0; i < a_rows; i++) {
*(c +i) = (double *)malloc(sizeof(double) * b_cols);
}
//clear matrix c
for(i = 0; i < a_rows; i++){
for(j = 0; j < a_cols; j++){
*c[j] = 0;
}
}
i = 0;
//multiplication
while(j = 0, i < a_rows ){
while(k = 0, j < b_cols){
while(k < a_cols){
//following line is where i'm getting the segmentation fault
*(*(c+(i*b_cols))+j) += (*(*(a+(i*a_cols))+k)) * (*(*(b+(k*b_cols))+j));
k++;
}
j++;
}
i++;
}
return c;
}
The obvious mistake is that you dereference c + i * b_cols while c is an array of pointers of size a_rows. So likely c + i * b_cols is outside of the area that you previously allocated with malloc().
I would suggest to simplify the matrix representation using a single array of double with the size equal to the total number of elements, i.e. rows * cols.
For example:
double *c;
c = malloc(sizeof(double) * a_rows * b_cols);
This not only has better overall performance, but simplifies the code. You would then have to "linearise" the offset inside your unidimensional array to convert from bi-dimensional matrix coordinates. For example:
c[i * b_cols + j] = ...
Of course, the other two matrices need to be allocated, filled and accessed in a similar manner.
For code clarity, I would also replace the while statements by for statements with the actual variable that they loop on. For example:
for (i = 0; i < a_rows; i++)
for (j = 0; j < b_cols; j++)
for (k = 0; k < a_cols; k++)
You can (ab)use the C language in many ways, but the trick is to make it more clear for you in the first place.
This code should multiply matrix A with matrix B and calculate matrix C.
matA 3x2, matB 2x3 therefore matC should be `3x3.
However, when I print matC, the 3rd row contains garbage values.
I don't know where the mistake is — if I do something wrong with the pointers or maybe the calculate part is wrong.
This is what I see when printing it.
x x 2489458943
x x 2489587641
x x 2489745734
Or something like that.
I don't know why sometimes it works.
I mean it prints the correct values, but most of the time this is what I see.
#include <stdio.h>
int main() {
int x = 0,y = 0, z = 0;
int i,j,k;
int **matA;
int **matB;
int **matC;
matA = (int**)malloc(sizeof(int)*3); // making the matrixes by malloc functions
matB = (int**)malloc(sizeof(int)*2);
matC = (int**)malloc(sizeof(int)*3);
for(i = 0; i < 3; i ++)
{
matA[i] = (int*)malloc(sizeof(int)*2); // matA 3x2
}
for(i = 0; i < 2; i++)
{
matB[i] = (int*)malloc(sizeof(int)*3); // matB 2x3
}
for(i = 0; i < 3; i++)
{
matC[i] = (int*)malloc(sizeof(int)*3); // the calculated mat 3x3
}
for(i = 0; i < 3; i++)
{
printf("please eneter line number: %i",i+1); //putting the values by scanf function in matA
printf(" seperated with ','\n");
scanf("%d,%d",&x,&y);
matA[i][0] = x;
matA[i][1] = y;
}
for(i = 0; i < 2; i++)
{
printf("please eneter line number: %i",i+1);// putting the values in matB
printf(" of the second mat seperated with ','");
scanf("%i,%i,%i", &x, &y, &z);
matB[i][0] = x;
matB[i][1] = y;
matB[i][2] = z;
}
for(i = 0; i < 3; i++) // multiple the matrixes by 3 loops
{
for(j = 0; j < 3; j++)
{
for(k = 0; k < 2; k++)
{
matC[j][i] += matA[j][k]*matB[k][i];
}
}
}
for(i = 0; i < 3; i ++)// just printing to check if the matrix correct
{
for(j = 0; j < 3; j++)
{
printf("%i ",(int**)matC[i][j]);
}
printf("\n");
}
return 0;
}
You're not allocating enough space in your matrixes:
matA = (int**)malloc(sizeof(int)*3);
matB = (int**)malloc(sizeof(int)*2);
matC = (int**)malloc(sizeof(int)*3);
You're allocating space for an array int but you need an array of int *. Most likely, pointers are larger than integers on your system which means your arrays aren't large enough to hold what you want and you run of the end of the array. Doing so invokes undefined behavior.
Allocate space for arrays of int *. Also, don't cast the return value of malloc:
matA = malloc(sizeof(int *)*3);
matB = malloc(sizeof(int *)*2);
matC = malloc(sizeof(int *)*3);
You're also adding to elements of matC without initializing them. You should set them to 0 before doing so:
matC[j][i] = 0;
for(k = 0; k < 2; k++)
{
matC[j][i] += matA[j][k]*matB[k][i];
}
You also don't need a cast here:
printf("%i ",(int**)matC[i][j]);
Since each matC[i][j] has type int and you're printing an int. This also invokes undefined behavior because the type of the expression doesn't match the type for the format specifier.
You never initialize matC and then use matC +=
The malloc function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. Try calloc instead.
Also, you have wrong int** initialization, should allocate pointer size sizeof(int*), not just sizeof(int):
matA = (int**)calloc(3, sizeof(int*));
matB = (int**)calloc(2, sizeof(int*));
matC = (int**)calloc(3, sizeof(int*));
I have a two-dimensional int array allocated as follows:
int **matrix = (int**)malloc(x * sizeof(int));
for (i = 0; i < x; i++)
matrix[i] = (int*)malloc(y * sizeof(int));
If I do realloc this array by the following code
int **matrix = (int**)realloc(matrix, x * sizeof(int));
for (i = 0; i < x; i++)
matrix[i] = (int*)malloc((y) * sizeof(int));
will there be any leftover "tails" of second dimension of the array and should I use free() function for them before reallocating, or they will go away themselves?
You will completely lose data in your matrix, so this is not really reallocing anything; you could just as well free and malloc the top-level array, getting possibly better performance. Furthermore your code would leak memory, because the 2nd level allocations are not freed.
Here is how you can resize the 2D matrix while keeping the current values intact, initializing the newly allocated cells to 0 and freeing any extra leftovers:
// matrix was allocated to x and y
// reallocate it to newx, newy
for (i = newx; i < x; i++) { /* free unneeded rows */
free(matrix[i]);
}
matrix = realloc(matrix, sizeof(*matrix) * newx);
for (i = x; i < newx; i++) { /* initialize the new row pointers */
matrix[i] = NULL;
}
for (i = 0; i < newx; i++) {
matrix[i] = realloc(matrix[i], sizeof(*matrix[i]) * newy);
for (int j = y; j < newy; j++)
matrix[i][j] = 0;
}