I'm still new to C, malloc, and all that jazz, so I decided to write this to learn some more skills. The idea is, I'm reading in a bunch of ints from a file and putting them into a matrix (2d array). The start of the file says how many rows and columns there are, so it reads those numbers in and uses malloc to set up the 2d array.
int read_matrix(FILE *mat, int ***Z, int *x, int *y)
{
int i = 0;
int x_temp = 0;
int y_temp = 0;
if (fscanf(mat, "%d %d", &(*x), &(*y)) == EOF){
printf("File is not big enough to contain a matrix\n");
return -1;
}
printf("About to malloc %d\n", *x);
*Z = (int**) malloc(*x * sizeof(int*));
while (i < *x) {
printf("mallocing %d\n", i);
*Z[i] = (int*) malloc(*y * sizeof(int));
printf("malloced\n");
++i;
}
printf("Malloc complete\n");
/*Other unimportant code*/
}
The output reads:
About to malloc 3
mallocing 0
malloced
mallocing 1
Segmentation fault
So it's not mallocing anything but one int** in Z.. I think?
I'm very new to C, so I'm not sure if I've made some little mistake, or if I'm really going about this whole thing incorrectly. Any thoughts? Thanks!
The [] operator binds more closely than the unary * operator. Try changing *Z[i] to (*Z)[i] and see if your code behaves.
As a side note, it's also quite common in C to malloc a single array of (sizex*sizey) size, for a matrix and then index it as arr[x*sizey + y] or arr[y*sizex + x]. That more closely mimics what the language does with static arrays (e.g. if you declare int foo[10][10], all 100 ints are contiguous in memory and nowhere is a list of 10 int*'s stored.
I agree with both Walter and AndreyT. This is just some additional information.
Note that you can get away with just two malloc() calls, rather than *x + 1 - one big block for the ints themselves, and one for the row index.
*Z = malloc(*x * sizeof (*Z)[0]);
(*Z)[0] = malloc(*x * *y * sizeof (*Z)[0][0]);
for (i = 1; i < *x; i++) {
(*Z)[i] = (*Z)[0] + i * *y;
}
As Walter correctly noted in his answer, it should be (*Z)[i] = ..., not *Z[i] = ....
On top of that I'd suggest getting rid of that dereference/typecast hell present in your source code. Don't cast the result of malloc. Don't use type names under sizeof. Expressing it as follows
*Z = malloc(*x * sizeof **Z);
...
(*Z)[i] = malloc(*y * sizeof *(*Z)[i]);
wil make your code type-independent and much more readable.
A separate question is what on Earth made you use &(*x) in fscanf. Is this some kind of bizarre coding standard?
Related
I have this problem in a bigger project, in which for some reason the realloc function does absolutely nothing. Am I missing something obvious?
Here is a simplified example:
#include <stdio.h>
#include <string.h>
int main()
{
int x = 1, y = 2, z = 3;
int* arr, *arr1;
int** arra;
arra = (int**)malloc(sizeof(int*));
arr = (int*)malloc(sizeof(int));
arr[0] = x;
arra[0] = arr;
arra = (int*)realloc(arra, sizeof(int*) + sizeof(int*));
arr1 = (int*)malloc(sizeof(int));
arr1[0] = y;
arra[1] = arr1;
}
When I debugged, the final arra was {{1}}, even though to my understanding it should be {{1},{2}}.
The debugger does not know that arra is any more than a single pointer. If you want the debugger to print out the contents of arra as an array, you need to walk the elements yourself, or cast it to an array type before printing.
First of all, how do you know that realloc has done nothing? Returning a different pointer is not warranted by realloc(3), as if possible it will try the realloc in place. Having said this, there's no way to know (externally to malloc) that it has done whatever you like or not, as the return value (being the same pointer) gives you no information about the new size.
By the way, how did you check if the sizes where the same or not. You don't show how you did in your code. Indeed, from your code you cannot get any information of the actual size returned by realloc (just see if the program crashed at all or not) If your used the sizeof operator, you are wrong, as you are using it with pointers and the size returned is always the same (the size of a pointer variable, an address) if you used the debugger, it has the same resources as the main program to check the size of whatever realloc returned (that is, nothing again) so, what is the reasoning to conclude that realloc is not working.
Next time, do several mallocs (not only two) and realloc all pointers to values much greater (to avoid optimizations leading to the same pointer returned) like this:
char *a = malloc(10), *b = malloc(10), *c = malloc(10);
char *aa = realloc(a, 10000), *bb = realloc(b, 10000), *cc = realloc(c, 10000);
if (a != aa || b != bb || c != cc)
printf("realloc *changed* the return values "
"(a=%p, aa=%p, b=%p, bb=%p, c=%p, cc=%p)\n",
a, aa, b, bb, c, cc);
else
printf("realloc didn't move the return values\n");
I wrote a C code that usea a matrix of double:
double y[LENGTH][4];
whith LENGTH=200000 I have no problem.
I have to increase the numbers of rows to LENGTH=1000000 but when I enter this value and execute the program it returns me segmentation fault.
I tried to allocate more memory using malloc:
double **y = (double **)malloc(LENGTH * sizeof(double*));
for(int i = 0; i < LENGTH; i++){
y[i] = (double *)malloc(4 * sizeof(double));
}
I run the the code above and after some second of calculations it still gives me "segmentation fault".
Could anyone help me?
If you want a dynamic allocated 2D array of the specified row-width, just do this:
double (*y)[4] = malloc(LENGTH * sizeof(*y));
There is no need to malloc each row in the matrix. A single malloc and free will suffice. Only if you need dynamic row width (each row can vary in width independent of others) or the column count is arbitrary should a nested malloc loop be considered. Neither appears to be your case here.
Notes:
Don't cast malloc in C programs
Be sure to free(y); when finished with this little tryst.
The reason your statically allocated array is segfaulting with a million elements is (presumably) because it's being allocated on the stack. To have your program have a larger stack, pass appropriate switches to your compiler.
ProTip: You will experience less memory fragmentation and better performance if you flip your loop around, allocating
(double *)malloc(LENGTH * sizeof(double));
four times. This will require changing the order of your indices.
I ran the the code with this definition and after some second of calculations it still gives me "segmentatin fault"
If you're getting a segmentation fault after allocating the memory, you're writing outside of your memory bounds.
I run this code
#include <stdio.h>
#include <stdlib.h>
// We return the pointer
int **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i, **table;
table = malloc(N*sizeof(int *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(int) );
return table;
}
void free2Darray(int** p, int N) {
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
int main(void)
{
const int LENGTH = 1000000;
int **p;
p = get(LENGTH, 4);
printf("ok\n");
free2Darray(p ,LENGTH);
printf("exiting ok\n");
return 0;
}
and it was executed normally.
I got the code from my pseudo-site.
You should not cast what malloc returns. Why?
Also notice, that since you need a dynamic allocation only for the number of rows, since you know the number of columns. So, you can modify the code yourself (so that you have some fun too. :) )
I hope you didn't forget to **free** your memory.
I am trying to develop the TicTacToe game in C and I am using the following structures.The myboard->a member is used to store 'X' or 'O' ,meaning the move a player has made in the same coordinates as the board , ie. 'X' in (1.1) or 'O' (3.1)
typedef struct{
int** a;
int size;
}_board;
typedef _board* board;
board myboard =(board) malloc(sizeof(board));
scanf_s("%d", &(myboard->size));
Size=is the size of the TicTacToe board nxn.
myboard->a =(int**)malloc(myboard->size*sizeof(char *));
if (myboard->a = NULL)
{
printf("ERROR!!!");
}
Until this point everything seems to work but when a try to allocate memory as you see bellow, a get a segmentation fault.
int i;
for (i = 0; j<myboard->size; i++)
{
myboard->a[i] = malloc(sizeof(char));
if (myboard->a[i] == NULL)
{
printf("ERROR");
}
}
I am using free for its malloc at the end of me program.
Thanks, in advance for any answer , and sorry for my bad english. Any help is apreciated.
I don't really understand why you are using a int** variable for storing your board data, when you could just use one simple int*, which you could later assign with malloc(3) as in:
int* b_data;
int b_size = 9;
b_data = malloc(b_size * sizeof(int));
// ... Your code
free(b_data);
If however, you really want to use a int** variable, you could do something like:
int** b_data;
int b_size_x = 3;
int b_size_y = 3;
int i;
b_data = malloc(b_size_x * sizeof(int*));
for(i = 0; i < b_size_x; i++)
*(b_data + i) = malloc(b_size_y * sizeof(int));
// ... Your code where you access your array of size_x containing
// arrays of size_y of int typed "cells"
for(i = 0; i < b_size_x; i++)
free(*(b_data + i));
free(b_data);
But this is really unnecessarily complicated, and I would dis-advise from doing so unless for learning purposes: in most cases, the allocated memory will be contiguous, so the second solution will allocate a nearly identical structure in memory, but will be less efficient (the "2D" array solution takes b_size_x times sizeof(int*) more memory), and the first solution will be simpler to read/write (so less prone to bugs, and easier to maintain).
Concerning your code, your problem is that myboard->a is NULL right after the "check" (which is in fact an allocation - note that the "ERROR" is never shown because myboard-> is then NULL, which evaluate to 'false'.):
if (myboard->a = NULL)
which should be:
if (myboard->a == NULL)
In addition, as pointed by #WhozCraig in his comment on your post, you might want to use i in the condition of your for loop, rather than j; and you also probably want to use int and int* types rather than char and char* types respectively in your malloc(s), since the a member of the board structure is an int**. Oh and also, think about putting newlines after your printf(3) strings, or use puts(3).
If this is a beginner's question, my apologies - most of my programming has been in very high level langauges, and I have limited expertise in C. (This is the sort of thing I could do very easily in languages such as Matlab, Octave, Sage, Maxima etc, but for this I need the speed of C).
But anyway... I have an array whose size is set at run time with malloc:
int *A = malloc(m * sizeof(int));
where m is computed from some values provided by the user. I have a function "update" which updates the array (or, if you prefer, takes the array as input and returns another as output). This update function may be called upwards of 10^8 times.
So the function itself can't introduce the appropriately sized output array with malloc, or the memory will be used up. So, for example, I can't do this:
int * update(int *L) /* produces next iteration of L */
{
int *out = malloc(m * sizeof(int));
/* do some stuff with L and produce new array out */
return (out);
}
I've tried to make out a static variable outside the update function:
static int *out;
and define its size in main:
out = malloc(m * sizeof(int));
But this doesn't seem to work either.
Anyway, I would be very grateful of some advice - I think I've exhausted the excellence of google.
Allocate the array outside of update, then pass a pointer to it:
void update(int const *L, int *out)
{
// whatever
}
Call as
int *A = malloc(m * sizeof(int));
if (A == NULL)
// handle error
for (i=0; i < N_ITER; i++)
update(L, A);
Though you may want to redesign the program so that it updates L in-place.
So if you are simply wanting to work on the data that is coming into the function directly, then what you have is partially already correct. The only thing that I would do is to add the size of the array as an input parameter to the routine to look like this:
void update(int * L, unsigned int size){
unsigned int count;
// Make sure the array has actually been allocated from outside
if(L == NULL) return;
// Example work on L just as if it is an array of values
for(count = 0; count < size; count++){
L[count] = L[count] + 1;
}
}
REMEMBER, this will work if you DO NOT wish to maintain the original data within L. If you do wish to maintain the original data, then larsmans answer will work better for you.
Also remember that you will have to malloc whatever variable you wish to input into L, outside and prior to your update routine, and free at some other point.
int * myVar = (int *)malloc(m * sizeof(int));
update(myVar, m);
// Other work to be done
free(myVar);
You should use realloc.
int *a = realloc(a, m * sizeof(a[0]));
It will work just as malloc in the first run but then it will reallocate a different sized array. You should note that the new array might or might not have the previous values assigned in it. You should assume that it has garbage like all things given by malloc.
Here is a good explanation of using realloc.
http://www.java-samples.com/showtutorial.php?tutorialid=589
NOTE : sizeof(a[0]) is equal to sizeof int but if you change int it will still be right
I'm attempting to create a simple 2D array in C but apparently running into some memory trouble. My setup is simple enough and I can't tell what's wrong. I admit that my understanding of pointers is insufficient, but I still think this should be working. Can anyone see the flaw here?
typedef unsigned int DATUM;
DATUM **series_of_data;
void initialize_data()
{
*series_of_data = (DATUM *) malloc(1024 * sizeof(DATUM));
}
This causes my program to crash with a bus error when I run it.
series_of_data is actually not allocated.
You have various way to allocates a 2D array, either using the array of rows model whcih has bad cache coherency and thus has usually bad performances or to use the Iliffe vector adviced in Numerical recipes in C that consists in allocating one huge h*w memory block and a side pointer array which contains the beginning of your rows (or columns) :
DATUM** alloc_array( int h, int w )
{
int i;
DATUM** m = (DATUM**)malloc(h*sizeof(DATUM*));
m[0] = (DATUM*)malloc(h*w*sizeof(DATUM));
for(i=1;i<h;i++) m[i] = m[i-1]+w;
return m;
}
void release_array(DATUM** m)
{
free( m[0] );
free( m);
}
int main()
{
int r,c;
DATUM** tab;
int width = 5;
int height = 3;
tab = alloc_array(height, width); /* column first */
for(r = 0;r<height;++r)
for(c = 0;c<width;++c)
tab[r][c] = (1+r+c);
for(r = 0;r<height;++r)
{
for(c = 0;c<width;++c)
{
printf("%d\t",tab[r][c]);
}
puts("");
}
release_array(tab);
}
Data are nicely packed in memory, so cache are happy and you keep the [][] access pattern.
As a matter of speed this is in +/-3% speed of the classical DATUM* + polynomial access method.
series_of_data is an invalid pointer - you don't assign it to anything. When you try to assign to its memory location (*series_of_data = ...), it's putting stuff in a random place, which is likely to not do what you want. You have to point series_of_data somewhere useful, e.g.
series_of_data = (DATUM **)malloc(16 * sizeof(DATUM *))
for an array with 16 slots for DATUM * pointers in it.
You haven't allocated the series_of_data pointer before you assign to *series_of_data.
For example, if series_of_data is intended to be an array then you would need to write something like this:
series_of_data = malloc(n*sizeof(DATUM*));
where n is the length of the series_of_data array.
Only after you have done this can you assign to *series_of_data.