Dynamically allocating, and filling up a variable, via a method in C - c

I'm having a great deal of difficulty with pointers. What I am trying to accomplish sounds, to my ears, rather simple: I want to define a multi-dimensional char array, but not its size, and then have a second method allocate the necessary memory, and fill it up with the requested data.
Now, I've tried for countless hours to accomplish this, searched with Google until my eyes were dry and I still haven't been able to fix it. As such I was hoping any of you had any insight how this would be possible.
What I am imagining, is to define a pointer char** files, and a counter int total_files that will be used my the method print_files(). Print files will then calloc and malloc the variable, and then we'll fill it up with relevant data.
Now in the code below, I have attempted this; however, at runtime I just get the magnificently detailed message: "Segmentation fault (core dumped)". Upon debugging with GDB it points at:
13 *files[i] = malloc(sizeof(char) * 100);
Now, this is for a introductory course to C programming (for Linux), and you might see numerous errors here. I do however, thank you for your time.
I had no issues getting the code to work without the method / pointers, so I'm sure I might just be mixing up the syntax somehow.
#define _SVID_SOURCE
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<dirent.h>
#include <time.h>
int print_files(char*** files, int* total_files) {
int size = 10;
**files = calloc(size, sizeof(char *));
for(int i = 0; i < size; i++) {
*files[i] = malloc(sizeof(char) * 100);
}
*total_files = size;
}
int main() {
char** files;
int num_files;
num_files = 0;
printf("-- Start print_files\n");
print_files(&files, &num_files);
printf("-- end print_files, number of files: %d\n", num_files);
for(int i = 0; i < num_files; i++)
printf("Out: %s\n", files[i]);
printf("total_files=%d\n", num_files);
return 0;
}

**files = calloc(size, sizeof(char *));
This assumes that not only files points to valid memory, but the value at that memory is also a valid pointer pointing to a pointer, which will be changed.
The problem is
char** files;
...
print_files(&files, &num_files);
&files is a valid pointer, but (**(&files)) (as dereferenced by print_files) is an illegal deference because files has not been initialized.
That print_files line should probably read
*files = calloc(size, sizeof(char *));
.
There is also a problem with
*files[i] = malloc(sizeof(char) * 100);
which is equivalent to
*(files[i]) = malloc(sizeof(char) * 100);
I think you probably mean
(*files)[i] = malloc(sizeof(char) * 100);

Here's a working version:
#include <stdio.h>
#include <stdlib.h>
static void print_files(char ***files, int *total_files)
{
int size = 10;
*files = calloc(size, sizeof(char *));
for (int i = 0; i < size; i++)
{
(*files)[i] = malloc(sizeof(char) * 100);
sprintf((*files)[i], "Line %d\n", i);
}
*total_files = size;
}
int main(void)
{
char **files;
int num_files;
num_files = 0;
printf("-- Start print_files\n");
print_files(&files, &num_files);
printf("-- end print_files, number of files: %d\n", num_files);
for(int i = 0; i < num_files; i++)
printf("Out: %s\n", files[i]);
printf("total_files=%d\n", num_files);
return 0;
}
The output is:
-- Start print_files
-- end print_files, number of files: 10
Out: Line 0
Out: Line 1
Out: Line 2
Out: Line 3
Out: Line 4
Out: Line 5
Out: Line 6
Out: Line 7
Out: Line 8
Out: Line 9
total_files=10
valgrind says "leaks like a sieve" but doesn't abuse memory while it is allocated.
What changed?
Triple pointers are scary. However, you want to use only one level of indirection in the assignment with calloc(). (With the double *, GCC warned that files in main() was used uninitialized!) Then, inside the loop, the parentheses around (*files) are critical too. The sprintf() simply serves to initialize the newly allocated string.
I didn't change the main() code significantly.

char **ppchar;
int x;
int y;
ppchar = (char**)malloc(sizeof(char*) * 100);
for (x = 0; x < 100; x++) {
ppchar[x] = (char*)malloc(sizeof(char) * 100);
}
for(x = 0; x < 100; x++) {
for(y = 0; y < 100; y++) {
ppchar[x][y] = rand() % 255; // ascii range
}
}
for(x = 0; x < 100; x++) {
for(y = 0; y < 100; y++) {
// char -128 to 127 or 0 to 255 - it's mostly machine
// dependent. This will tell you.
printf("%d\t",ppchar[x][y]);
}
}
//make sure to clean up the memory
for (x = 0; x < 100; x++) {
free(ppchar[x]);
}
free(ppchar);
return 0;
}

Related

Problem with free() function in C and memory-leaks

I've a problem about deallocating memory using free() in C.
My program generates a random genealogic tree using a matrix. This matrix can be very huge depending on the number of family members. The program seemed to work fine until I decided to generate more than one tree. I noticed that generating about 100 trees causes my 8GB RAM to fill! I'm sure I can make a better code to reduce the demand of memory, but my problem remains.
I use free() to deallocate memory and there's no error. I installed Valgrind to se what's happening and it says that about 100 million byte per tree are definitely lost. This means that free() doesn't work fine. I don't now where is the problem. I link some functions that I think are correlated to the problem.
typedef struct{
int f_id;
char f_name[L_NAMES];
int generations;
int n_members;
type_people *members;
int_mtx *mtx;
}type_family;
The struct above is for the family.
typedef struct temp{
int p_id;
char name[L_NAMES];
char f_name[L_NAMES];
int generation;
int n_sons;
struct temp **sons;
int f_id;
int sex;
int age;
}type_people;
This is for the members.
typedef struct{
int i;
int j;
int **val;
}int_mtx;
And the matrix.
In the main i call the function to initialize the tree:
type_family *family_a;
family_a = malloc(sizeof(type_family));
family_a = init_family_n_gen(family_a, 6);
This is the frist part of init_family_n_gen():
type_family *init_family_n_gen(type_family *family, int n){
...
family->members = malloc(max_people * sizeof(type_people));
family->mtx = mtxcalloc(family->mtx, max_people, max_people - 1);
...
This code is for mtxcalloc that initializes the matrix:
int_mtx *mtxcalloc(int_mtx *mtx, int i, int j){
mtx = malloc(sizeof(int_mtx));
mtx->i = i;
mtx->j = j;
mtx->val = malloc(i * sizeof(int *));
for(int a = 0; a < i; a++){
mtx->val[a] = malloc(j * sizeof(int));
for(int b = 0; b < j; b++){
mtx->val[a][b] = 0;
}
}
return mtx;
}
And to conclude the code to deallocate the family:
void free_family(type_family *family){
for(int m = 0; m < family->n_members; m++){
if(family->members[m].n_sons != 0){
free(family->members[m].sons);
}
}
mtxfree(family->mtx);
free(family->members);
}
And the one to deallocate the matrix:
void mtxfree(int_mtx *mtx){
for(int i = 0; i < mtx->i; i++){
free(mtx->val[i]);
}
free(mtx->val);
free(mtx);
}
Screen capture of Valgrind output
So I call the free_family(family_a) every time i need to regenerate the family but the memory still increases. (In the photo above the number of byte become 1 billion if i regenerate the family for 50 times).
Thanks for the support!
EDITED
I made a minimal reproducible example that emulates my original code. The structs and variables are the same but I changed the functions according to Weather Vane: they are all void and I pass them the double **.
The init_family_n_gen becomes:
void init_family(type_family **f){
type_family *family = malloc(sizeof(type_family));
family->members = malloc(100 * sizeof(type_people));
for(int m = 0; m < 100; m++){
family->members[m].n_sons = 0;
}
mtxcalloc(&family->mtx, 100, 99);
family->mtx->val[0][1] = 7;
family->mtx->val[9][8] = 1;
mtxrealloc(&family->mtx, 5, 4);
*f = family;
}
The main is:
type_family *family_a;
init_family(&family_a);
free_family(&family_a);
The only thing I added is this function(Is the code right?):
void mtxrealloc(int_mtx **mtx, int i, int j){
(*mtx)->i = i;
(*mtx)->j = j;
(*mtx)->val = realloc((*mtx)->val, (*mtx)->i * sizeof(int *));
for(int a = 0; a < (*mtx)->i; a++){
(*mtx)->val[a] = realloc((*mtx)->val[a], (*mtx)->j * sizeof(int));
}
}
I noticed that the problem occours when i use the realloc function and i can't figure why. I link the images of Valgrind with and without the function mtxrealloc. (I see that there is aslo a 48 byte leak...).
Valgrind with realloc
Valgrind without realloc
Thanks again for your support!
This:
init_family(&family_a);
Causes this code from mtxcalloc to execute:
mtx->val = malloc(i * sizeof(int *));
for(int a = 0; a < i; a++){
mtx->val[a] = malloc(j * sizeof(int));
for(int b = 0; b < j; b++){
mtx->val[a][b] = 0;
}
}
, with i, j = 100, 99. That is, you allocate space for 100 pointers, and for each one, you allocate space for 99 ints. These are then accessible via family_a->mtx.
Very shortly thereafter, you make this call:
mtxrealloc(&family->mtx, 5, 4);
, which does this, among other things:
(*mtx)->val = realloc((*mtx)->val, (*mtx)->i * sizeof(int *));
That loses all the pointers (*mtx)->val[5] through (*mtx)->val[99], each of which is the sole pointer to allocated space sufficient for 99 ints. Overall, sufficient space for 9405 ints is leaked before you even perform any computations with the object you are preparing.
It is unclear why you overallocate, just to immediately (attempt to) free the excess, but perhaps that's an artifact of your code simplification. It would be much better to come up with a way to determine how much space you need in advance, and then allocate only that much in the first place. But if you do need to reallocate this particular data, then you need to first free each of the (*mtx)->val[x] that will be lost. Of course, if you were going to reallocate larger, then you would need to allocate / reallocate all of the (*mtx)->val[x].

Seg Fault when accessing an array initialised with malloc

Below is a simplified extract of a program I'm writing. I'm having issues accessing elements towards the end of the array.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int n, char *args[n]){
// create 4D array scores[10000][100][100][100] on heap
uint64_t arraySize = 1; // this avoids overflow
arraySize *= 10000;
arraySize *= 100;
arraySize *= 100;
arraySize *= 100;
int (*scores)[10000][100][100] = malloc(arraySize);
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 100; j++) {
printf("%d, %d, %d\n", i, j, scores[i][j][0][0]);
}
}
}
The program loops through the 4D array score and as a test I'm printing the contents of the array. The loop starts off as planned, printing in the format "i, j, 0" for each i and j, until the last success "25, 0, 0".
From this point on I get random numbers rather than 0, starting with "25, 1, 1078528" up until "25, 45, 1241744152" which is then followed by "Segmentation fault (core dumped)".
After fiddling around I found the first non-zero array member to be scores[25][0][7][64].
So I guess I'm running out of space and so am accessing memory I shouldn't be? If anyone knows or has an idea as to how I could fix this I'd really appreciate it.
My PC is running Ubuntu 16.10 64bit, has 16GB RAM and 16GB swap
Edit
After implementing the following suggestions I get a return value of "calloc: Cannot allocate memory".
int (*scores)[100][100][100] = calloc(arraySize, sizeof(int));
if (scores == NULL) {
perror("calloc");
return 1;
}
If I comment out the new if statement (and run the for loop) I get an immediate seg fault. This also happens if I use malloc:
int (*scores)[100][100][100] = malloc(arraySize * sizeof(int));
Why could this be? Surely my system has enough memory
Cheers
Check the return value of malloc() and determine if it failed to allocate.
You forgot to multiply the size of int.
The type of result should be int (*)[100][100][100], not int (*)[10000][100][100].
Using value of buffer allocated via malloc() and not initialized invokes undefined behavior, so don't do that.
Try this:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int n, char *args[n]){
// create 4D array scores[10000][100][100][100] on heap
uint64_t arraySize = 1; // this avoids overflow
arraySize *= 10000;
arraySize *= 100;
arraySize *= 100;
arraySize *= 100;
int (*scores)[100][100][100] = calloc(arraySize, sizeof(int));
if (scores == NULL) {
perror("calloc");
return 1;
}
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 100; j++) {
printf("%d, %d, %d\n", i, j, scores[i][j][0][0]);
}
}
}
Your pointer to a variable length array does not use correct array sizes.
The array is: [10000][100][100][100]
but the pointer is: [100][10000][100][100]
And you need to multiply the array size times the size of the object, in this case size of type int.
The pointer definition should be:
int (*scores)[100][100][100] = malloc(arraySize*sizeof(int));
The allocated elements are not initialized. Reading them will yield indeterminate values.
The correct type to store the size of bytes that need to be allocated, is size_t, not uint64_t.
One of the correct ways to allocate the array is:
const size_t bytes = sizeof( int[10000][100][100][100] );
int (*scores)[100][100][100] = malloc( bytes );
(This of course assumes that size_t can represent that value.)
Did you try:
int (*scores)[10000][100][100] = malloc(sizeof(int)*arraySize);
Bye.

Accessing array malloced inside a function from outside - unexpected results

I have a function designed to malloc an array and then fill it with values from a file (n-dimensional coordinates, although working in 2d for now).
#include <stdio.h>
#include <stdlib.h>
#define dim 2
typedef struct {
double **array; /*store the coordinates*/
int num; /* store the number of coordinates*/
/* store some other things too */
} foo;
void read_particles(foo *bar);
int main(void)
{
foo bar;
read_particles(&bar);
printf("\n");
for(int i = 0; i < bar.num; i++)
printf("%f %f\n", bar.array[0][i], bar.array[1][i]);
/* printf here does not output the array properly.
* Some values are correct, some are not.
* Specifically, the first column bar.array[0][i] is correct,
* the second column bar.array[1][i] is not, some values from the
* first column are appearing in the second.
*/
return 0;
}
void read_particles(foo *bar)
{
FILE *f = fopen("xy.dat", "r");
/* read number of coordinates from file first*/
fscanf(f, "%d", &bar->num);
bar->array = (double**) malloc(bar->num * sizeof(double*));
for(int i = 0; i < bar->num; i++)
bar->array[i] = (double*) malloc(dim * sizeof(double));
for(int i = 0; i < bar->num; i++)
{
for(int j = 0; j < dim; j++)
fscanf(f, "%lf", &(bar->array[j][i]));
/* For now, coordinates are just 2d, print them out
* The values are displayed correctly when printing here*/
printf("%f %f\n", bar->array[0][i], bar->array[1][i]);
}
fclose(f);
}
Some sample data is available here.
When the values are printed from inside the function they are fine, when printed outside the function they are not. So I must not be dealing with the pointers properly. It may (or may not) be worth noting that I originally was not using a struct and had the function defined as double **read_and_malloc(num), returning the pointer to the array, and the output produced was identical.
So what is going on?
I can include some sample data, or any other information if need be.
Your second loop is not correct:
for(int i = 0; i < dim; i++)
bar->array[i] = (double*) malloc(dim * sizeof(double));
You create bar->num elements yet you iterate over dim elements:
bar->array = (double**) malloc(bar->num * sizeof(double*))
The loop should iterate over the number of elements in the first dimension: bar->num
In the updated code you are allocating bar->num rows and 2 columns. However, your fscanf and printf code tries to work on array with 2 rows and bar->num columns.
To keep your reading/writing code intact, the allocation code would be:
bar->array = malloc(dim * sizeof *bar->array);
for (int i = 0; i < dim; ++i)
bar->array[j] = malloc(bar->num * sizeof *bar->array[j]);
NB. If you're not familiar with this malloc idiom, see here

Segmentation fault (core dumped) [Conway's game of life]

I'm working on a C implementation for Conway's game of life, I have been asked to use the following header:
#ifndef game_of_life_h
#define game_of_life_h
#include <stdio.h>
#include <stdlib.h>
// a structure containing a square board for the game and its size
typedef struct gol{
int **board;
size_t size;
} gol;
// dynamically creates a struct gol of size 20 and returns a pointer to it
gol* create_default_gol();
// creates dynamically a struct gol of a specified size and returns a pointer to it.
gol* create_gol(size_t size);
// destroy gol structures
void destroy_gol(gol* g);
// the board of 'g' is set to 'b'. You do not need to check if 'b' has a proper size and values
void set_pattern(gol* g, int** b);
// using rules of the game of life, the function sets next pattern to the g->board
void next_pattern(gol* g);
/* returns sum of all the neighbours of the cell g->board[i][j]. The function is an auxiliary
function and should be used in the following function. */
int neighbour_sum(gol* g, int i, int j);
// prints the current pattern of the g-board on the screen
void print(gol* g);
#endif
I have added the comments to help out with an explanation of what each bit is.
gol.board is a 2-level integer array, containing x and y coordinates, ie board[x][y], each coordinate can either be a 1 (alive) or 0 (dead).
This was all a bit of background information, I'm trying to write my first function create_default_gol() that will return a pointer to a gol instance, with a 20x20 board.
I then attempt to go through each coordinate through the 20x20 board and set it to 0, I am getting a Segmentation fault (core dumped) when running this program.
The below code is my c file containing the core code, and the main() function:
#include "game_of_life.h"
int main()
{
// Create a 20x20 game
gol* g_temp = create_default_gol();
int x,y;
for (x = 0; x < 20; x++)
{
for (y = 0; y < 20; y++)
{
g_temp->board[x][y] = 0;
}
}
free(g_temp);
}
// return a pointer to a 20x20 game of life
gol* create_default_gol()
{
gol* g_rtn = malloc(sizeof(*g_rtn) + (sizeof(int) * 20 * 20));
return g_rtn;
}
This is the first feature I'd like to implement, being able to generate a 20x20 board with 0's (dead) state for every coordinate.
Please feel free to criticise my code, I'm looking to determine why I'm getting the segmentation fault, and if I'm allocating memory properly in the create_default_gol() function.
Thanks!
The type int **board; means that board must contain an array of pointers, each of which points to the start of each row. Your existing allocation omits this, and just allocates *g_rtn plus the ints in the board.
The canonical way to allocate your board, supposing that you must stick to the type int **board;, is:
gol* g_rtn = malloc(sizeof *g_rtn);
g_rtn->size = size;
g_rtn->board = malloc(size * sizeof *g_rtn->board);
for (int i = 0; i < size; ++i)
g_rtn->board[i] = malloc(size * sizeof **g_rtn->board);
This code involves a lot of small malloc chunks. You could condense the board rows and columns into a single allocation, but then you also need to set up pointers to the start of each row, because board must be an array of pointers to int.
Another issue with this approach is alignment. It's guaranteed that a malloc result is aligned for any type; however it is possible that int has stricter alignment requirements than int *. My following code assumes that it doesn't; if you want to be portable then you could add in some compile-time checks (or run it and see if it aborts!).
The amount of memory required is the sum of the last two mallocs:
g_rtn->board = malloc( size * size * sizeof **g_rtn->board
+ size * sizeof *g_rtn->board );
Then the first row will start after the end of the row-pointers (a cast is necessary because we are converting int ** to int *, and using void * means we don't have to repeat the word int):
g_rtn->board[0] = (void *) (g_rtn->board + size);
And the other rows each have size ints in them:
for (int i = 1; i < size; ++i)
g_rtn->board[i] = g_rtn->board[i-1] + size;
Note that this is a whole lot more complicated than just using a 1-D array and doing arithmetic for the offsets, but it was stipulated that you must have two levels of indirection to access the board.
Also this is more complicated than the "canonical" version. In this version we are trading code complexity for the benefit of having a reduced number of mallocs. If your program typically only allocates one board, or a small number of boards, then perhaps this trade-off is not worth it and the canonical version would give you fewer headaches.
Finally - it would be possible to allocate both *g_rtn and the board in the single malloc, as you attempted to do in your question. However my advice (based on experience) is that it is simpler to keep the board separate. It makes your code clearer, and your object easier to use and make changes to, if the board is a separate allocation to the game object.
create_default_gol() misses to initialise board, so applying the [] operator to it (in main() ) the program accesses "invaid" memory and with ethis provokes undefined behaviour.
Although enough memory is allocated, the code still needs to make board point to the memory by doing
gol->board = ((char*) gol) + sizeof(*gol);
Update
As pointed out by Matt McNabb's comment board points to an array of pointers to int, so initialisation is more complicate:
gol * g_rtn = malloc(sizeof(*g_rtn) + 20 * sizeof(*gol->board));
g_rtn->board = ((char*) gol) + sizeof(*gol);
for (size_t i = 0; i<20; ++i)
{
g_rtn->board[i] = malloc(20 * sizeof(*g_rtn->board[i])
}
Also the code misses to set gol's member size. From what you tell us it is not clear whether it shall hold the nuber of bytes, rows/columns or fields.
Also^2 coding "magic numbers" like 20 is bad habit.
Also^3 create_default_gol does not specify any parameters, which explictily allows any numberm and not none as you might perhaps have expected.
All in all I'd code create_default_gol() like this:
gol * create_default_gol(const size_t rows, const size_t columns)
{
size_t size_rows = rows * sizeof(*g_rtn->board));
size_t size_column = columns * sizeof(**g_rtn->board));
gol * g_rtn = malloc(sizeof(*g_rtn) + size_rows);
g_rtn->board = ((char*) gol) + sizeof(*gol);
if (NULL ! = g_rtn)
{
for (size_t i = 0; i<columns; ++i)
{
g_rtn->board[i] = malloc(size_columns); /* TODO: Add error checking here. */
}
g_rtn->size = size_rows * size_columns; /* Or what ever this attribute is meant for. */
}
return g_rtn;
}
gol* create_default_gol()
{
int **a,i;
a = (int**)malloc(20 * sizeof(int *));
for (i = 0; i < 20; i++)
a[i] = (int*)malloc(20 * sizeof(int));
gol* g_rtn = (gol*)malloc(sizeof(*g_rtn));
g_rtn->board = a;
return g_rtn;
}
int main()
{
// Create a 20x20 game
gol* g_temp = create_default_gol();
int x,y;
for (x = 0; x < 20; x++)
{
for (y = 0; y < 20; y++)
{
g_temp->board[x][y] = 10;
}
}
for(x=0;x<20;x++)
free(g_temp->board[x]);
free(g_temp->board);
free(g_temp);
}
main (void)
{
gol* gameOfLife;
gameOfLife = create_default_gol();
free(gameOfLife);
}
gol* create_default_gol()
{
int size = 20;
gol* g_rtn = malloc(sizeof *g_rtn);
g_rtn = malloc(sizeof g_rtn);
g_rtn->size = size;
g_rtn->board = malloc(size * sizeof *g_rtn->board);
int i, b;
for (i = 0; i < size; ++i){
g_rtn->board[i] = malloc(sizeof (int) * size);
for(b=0;b<size;b++){
g_rtn->board[i][b] = 0;
}
}
return g_rtn;
}
Alternatively, since you also need to add a create_gol(size_t new_size) of custom size, you could also write it as the following.
main (void)
{
gol* gameOfLife;
gameOfLife = create_default_gol();
free(gameOfLife);
}
gol* create_default_gol()
{
size_t size = 20;
return create_gol(size);
}
gol* create_gol(size_t new_size)
{
gol* g_rtn = malloc(sizeof *g_rtn);
g_rtn = malloc(sizeof g_rtn);
g_rtn->size = new_size;
g_rtn->board = malloc(size * sizeof *g_rtn->board);
int i, b;
for (i = 0; i < size; ++i){
g_rtn->board[i] = malloc(sizeof (int) * size);
for(b=0;b<size;b++){
g_rtn->board[i][b] = 0;
}
}
return g_rtn;
}
Doing this just minimizes the amount of code needed.

Segmentation fault when using malloc for 2D array

I create a 2-D array using malloc. When I use printf to print the array element in for loop, everything is fine. But when I want to use printf in main, these is a Segmentation fault: 11.
Could you please tell me what the problem with the following code is?
#include <stdlib.h>
#include <stdio.h>
void initCache(int **cache, int s, int E){
int i, j;
/* allocate memory to cache */
cache = (int **)malloc(s * sizeof(int *)); //set
for (i = 0; i < s; i++){
cache[i] = (int *)malloc(E * sizeof(int)); //int
for(j = 0; j < E; j++){
cache[i][j] = i + j;
printf("%d\n", cache[i][j]);
}
}
}
main()
{
int **c;
initCache (c, 2, 2);
printf("%d\n", c[1][1]); // <<<<<<<<<< here
}
Since your cache is a 2D array, it's int**. To set it in a function, pass int***, not int**. Otherwise, changes to cache made inside initCache have no effect on the value of c from main().
void initCache(int ***cache, int s, int E) {
int i, j;
/* allocate memory to cache */
*cache = (int **)malloc(s * sizeof(int *)); //set
for (i = 0; i < s; i++) {
(*cache)[i] = (int *)malloc(E * sizeof(int)); //int
for(j = 0; j < E; j++){
(*cache)[i][j] = i + j;
printf("%d\n", (*cache)[i][j]);
}
}
}
Now you can call it like this:
initCache (&c, 2, 2);
You changed a local variable, which won't effect the local variable c in main.
If you want to allocate in the function, why pass a variable? Return it from the function.
int **c = initCache(2, 2);
You could use a return, or else a *** as suggested by others. I'll describe the return method here.
initCache is creating and initializing a suitable array, but it is not returning it. cache is a local variable pointing to the data. There are two ways to make this information available to the calling function. Either return it, or pass in an int*** and use that to record the pointer value.
I suggest this:
int** initCache(int **cache, int s, int E){
....
return cache;
}
main()
{
int **c;
c = initCache (2, 2);
printf("%d\n", c[1][1]); <<<<<<<<<< here
}
====
Finally, it's very important to get in the habit of checking for errors. For example, malloc will return NULL if it has run out of memory. Also, you might accidentally as for a negative amount of memory (if s is negative). Therefore I would do:
cache = (int **)malloc(s * sizeof(int *));
assert(cache);
This will end the program if the malloc fails, and tell you what line has failed. Some people (including me!) would disapprove slightly of using assert like this. But we'd all agree it's better than having no error checking whatsoever!
You might need to #include <assert.h> to make this work.

Resources