Border values in table overwrite neighbours - c

I am writing a C program, in which I try to dynamically allocate a 2-dim array (or an array of arrays.) After the table is allocated I try to iterate over it, but it throws an error about illegal memory access and creates a coredump.
After some investigation I've found out a curious thing: the array I experiment with is 4x4, but when I set array[0][3] = 123; it sets both [0][3] and [1][0] positions to be 123. Exactly the same thing happens if I assign array[1][0] = 123;, as it sets both [0][3] and [1][0] to the rightside value. Similar assignment is done for any "border values", like [2][0] and [1][3]. I guess something must be wrong with my allocation, but I can't figure it out. I was pretty sure that this is the way to dynamically allocate multi-dim arrays and a bit of research confirmed it. Here is my code (I know it should be SSSCE but I can't provide it shorter and still show the problem):
typedef struct {
int rows;
int columns;
double **data;
} matrix;
matrix* allocateMatrix(int inputRows, int inputColumns) {
matrix *matrixPointer = calloc(1, sizeof(matrix));
matrixPointer->rows = inputRows;
matrixPointer->columns = inputColumns;
#ifdef DOUBLE
matrixPointer->data = calloc(inputRows, sizeof(double*));
#else
matrixPointer->data = calloc(inputRows, sizeof(float*));
#endif
if (matrixPointer->data == NULL) {
printf("Error - inputRows value appears to be wrong.");
return NULL;
}
int i, j;
for (i = 0; i < inputRows; i++) {
#ifdef DOUBLE
matrixPointer->data[i] = calloc(inputColumns, sizeof(double));
#else
matrixPointer->data[i] = calloc(inputColumns, sizeof(float));
#endif
if (matrixPointer->data[i] == NULL) {
printf("Error - inputColumns value appears to be wrong.");
return NULL;
}
}
matrixPointer->data[2][0] = 123; //TEST CODE;
return matrixPointer;
}
And some code to see the contents of such created array:
matrix *lol = allocateMatrix(4, 4);
int i, j;
for (i = 0; i < lol->rows; i++)
for (j = 0; j < lol->columns; j++)
printf("%f ", lol->data[i][j]);
Is my memory allocation wrong, or maybe some other issue I fail to see. I would be grateful for any suggestions or help. Thank you in advance.

typedef struct {
int rows;
int columns;
double **data;
} matrix;
This is the culprit. The DOUBLE macrodefinition was supposed to enable double precision through the code, but when the flag was not set the code still allocated double** data, causing possible segmentation faults. The correct code in this case should look like:
typedef struct {
int rows;
int columns;
#ifdef DOUBLE
double **data;
#else
float **data;
#endif
} matrix;

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].

C string pointer initializes itself then de-initializes itself?

This is an excerpt from a Conway's Game of Life-program that I'm writing. In this part I'm trying to get the program to read a file that specifies what cells are to be populated at the start of the game (i.e. the seed).
I get a weird bug. In the read_line function, the program crashes online[i++] = ch statement. When I debug the program, I see that the line-pointer is NULL when it crashes. Fair enough, I think, I should initialize line. But here is the (for me) strange part:
The read_line function has already successfully execute twice and got me the first two lines (4\n and 3 6\n) from the seed file. And when I look at the execution in the debugger, I see that line is indeed holding a value in those first two executions of read_line. How is this possible? How can line be initialized without me initializing it and then suddenly not be initialized anymore?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define MAX_COORDINATE_SIZE 50
#define MAX_FILENAME_SIZE 20
#define MAX_GENERATIONS 10
#define MAX_REPETITION_PERIOD 4
struct coord{ //Holds coordinates to a cell
int x;
int y;
};
struct cell{
int pop; //Populated
int age;
};
struct coord *read_init(FILE *fp, int *i);
static int read_line(FILE *fp, char *line, int max_length);
struct coord read_coords(char *line);
struct cell **create_board(int x, int y);
struct cell **start_game(FILE *fp, int nrows, int ncols);
struct cell new_cell(int x, int y, int pop, int age);
void print_board(struct cell **board, int nrows, int ncols);
void populate_board(struct coord *coords, struct cell ***board, int *n);
int main(int argc, const char * argv[]) {
int gens;
char gens_string[MAX_GENERATIONS];
if(argc != 3){
fprintf(stderr, "Usage: %s <seed-file> <generations>\n<seed-file> can me up to %d characters long\n", argv[0], MAX_FILENAME_SIZE);
exit(1);
}
FILE *fp = fopen(argv[1], "r");
strncat(gens_string, argv[2], MAX_GENERATIONS);
gens = atoi(gens_string);
int nrows = 10;
int ncols = 10;
struct cell **board= start_game(fp, nrows, ncols);
print_board(board, nrows, ncols);
return 0;
}
struct coord *read_init(FILE *fp, int *n){ //Takes in filename and returns list of coordinates to be populated
char raw_n[100];
struct coord *coords;
char *line;
read_line(fp, raw_n, 100); // get the first line of the file (number of popuated cells)
*n = atoi(raw_n);//make an int out of raw_n
coords = malloc(sizeof(struct coord)*(*n)); //Allocate memory for each coord
for(int i = 0; i<(*n); i++){ // for each line in the file (each populated cell)
read_line(fp, line, MAX_COORDINATE_SIZE);
coords[i] = read_coords(line); //Put coordinates in coords
line = '\0';
}
return coords; // return coordinates
}
static int read_line ( FILE *fp, char *line, int max_length)
{
int i;
char ch;
/* initialize index to string character */
i = 0;
/* read to end of line, filling in characters in string up to its
maximum length, and ignoring the rest, if any */
for(;;)
{
/* read next character */
ch = fgetc(fp);
/* check for end of file error */
if ( ch == EOF )
return -1;
/* check for end of line */
if ( ch == '\n' )
{
/* terminate string and return */
line[i] = '\0';
return 0;
}
/* fill character in string if it is not already full*/
if ( i < max_length )
line[i++] = ch;
}
/* the program should never reach here */
return -1;
}
struct coord read_coords(char *line){ // Returns coordinates read from char *line
struct coord c;
char *x;
char *y;
x = malloc(sizeof(char)*MAX_COORDINATE_SIZE);
y = malloc(sizeof(char)*MAX_COORDINATE_SIZE);
int i = 0;
do{
x[i] = line[i]; //Get the x coordinate
i++;
}while(line[i] != ' ');
i++;
do{
y[i-2] = line[i];
i++;
}while(line[i] != '\0');
c.x = atoi(x)-1;
c.y = atoi(y)-1;
return c;
}
void init_board(int nrows, int ncols, struct cell ***board){
*board = malloc(nrows * sizeof(*board) + nrows * ncols * sizeof(**board));
//Now set the address of each row or whatever stackoverflow says
struct cell * const firstrow = *board + nrows;
for(int i = 0; i < nrows; i++)
{
(*board)[i] = firstrow + i * ncols;
}
for(int i = 0; i < nrows; i++){ //fill the entire board with pieces
for(int j = 0; j < ncols; j++){
(*board)[i][j] = new_cell(i, j, 0, 0);
}
}
}
void print_board(struct cell **board, int nrows, int ncols){
printf("--------------------\n");
for(int i = 0; i<nrows; i++){
for(int j = 0; j<ncols; j++){
if(board[i][j].pop == 1){
printf("%d ", board[i][j].age);
}else if(board[i][j].pop == 0){
printf(" ");
}else{
printf("\n\nERROR!");
exit(0);
}
}
printf("\n");
}
printf("--------------------");
printf("\n");
}
struct cell **start_game(FILE *fp, int nrows, int ncols){ //x,y are no of rows/columns, fn is filename
int n; // n is the number of populated cells specified in the seed
struct coord *coords = read_init(fp, &n); // get the list of coords to populate board with
struct cell **board;
init_board(nrows, ncols, &board); // Set up the board
populate_board(coords, &board, &n); //populate the cells specified in the seed
return board;
}
void populate_board(struct coord *coords, struct cell ***board, int *n){
for(int i = 0; i < *n; i++){
(*board)[coords[i].x][coords[i].y].pop = 1; //populate the cell
}
}
struct cell new_cell(int x, int y, int pop, int age){ //Return new populated or non-populated cell with specified coordinates
struct cell c;
c.pop = pop;
c.age = age;
return c;
}
The seed file:
4
3 6
4 6
5 6
5 7
EDIT:
The error message: Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
I shall add that if I add a line line = malloc(sizeof(char)*MAX_COORDINATE_SIZE+1) after the declaration of line in read_init, I still get the same error.
In read_init() :
struct coord *read_init(FILE *fp, int *n){
//...
char *line;
//...
for(int i = 0; i<(*n); i++) {
read_line(fp, line, MAX_COORDINATE_SIZE);
coords[i] = read_coords(line); //Put coordinates in coords
line = '\0'; // <<--- you set line to NULL here.
*line = 0; // this is what you wanted to do, is not necessary...
}
// ....
}
I get a weird bug.
I suggest asking some questions about the compiler output. We should never blindly ignore warnings, after all. Speaking of reading things, I think you're spending too long reading StackOverflow and not long enough reading K&R2e and doing the exercises. We'll come back to that.
In the read_line function, the program crashes on line[i++] = ch statement ... But here is the (for me) strange part: ... The read_line function has already successfully execute twice and got me the first two lines (4\n and 3 6\n) from the seed file
The C and C++ standards rationalise the concept of "undefined behaviour" for this class of errors that are computationally difficult to diagnose. In other words, because you made an error, the behaviour of your program is undefined. It isn't required that your malfunctioning code crash every time, as that would be defining the undefined; instead they leave this "undefined" and the first two times your erroneously code works (whatever that means), purely by coincidence that the uninitialised variable points somewhere accessible. Later on you assign line = '\0';, which changes line to be a null pointer, and then you try to assign into whatever that null pointer points at. That's more undefined behaviour.
How is this possible? How can line be initialized without me initializing it and then suddenly not be initialized anymore?
line isn't initialised; you're using it uninitialised, which happens to coincidentally work (but needs fixing), then you assign it to be a null pointer and dereference a null pointer (more UB that needs fixing). Such is the nature of undefined behaviour. Such is the nature of learning C by guessing. You need a book!
I shall add that if I add a line line = malloc(sizeof(char)*MAX_COORDINATE_SIZE+1) after the declaration of line in read_init, I still get the same error.
You need to fix all of the errors, not just the one. For assistance you could see the warnings/errors your compiler emits. I see more uninitialised access here:
char gens_string[MAX_GENERATIONS]; // <--- where's the initialisation??
// Snip
strncat(gens_string, argv[2], MAX_GENERATIONS); // Boom
There's some really sus code around this comment: //Now set the address of each row or whatever stackoverflow says ... and on that note I want to point out that there are some subtly toxic know-it-alls who answer questions despite having as many misunderstandings as you, a humble person, and so you shouldn't hope to get the same quality of education from StackOverflow as you would from K&R2e... but apparently I'd be toxic for pointing out the egomaniacs and suggesting decent resources to learn from, so that's none of my business 🙄🤷‍♂️ let's just let the sociopaths sabotage the education of everyone huh?
(*board)[i] = firstrow + i * ncols;
Look, there is no guarantee that this even compiles let alone that the address on the right has a suitable alignment to store the type of value on the left. Misaligned access causes more undefined behaviour, which may also work coincidentally rather than logically. Just as you've never seen alignment violations before, so too has the person who suggested you use this code. Assuming the alignment requirements for your implementation are satisfied by this code, we then have the same questions to raise here:
(*board)[i][j] = new_cell(i, j, 0, 0);
Your whole program needs remodelling around the declaration of board changing from struct cell **board to struct cell (*board)[ncols];, for example. It'll become much simpler, and a whole class of bugs related to alignment requirements will disappear. To see the extent of the simplification, here's what your init_board ought to look like:
void init_board(int nrows, int ncols, struct cell (**board)[ncols]){
*board = malloc(nrows * sizeof(*board));
// NOTE: I snipped the erroneous StackOverflow logic around the comment mentioned above; you don't need that crud because of the more suitable choice of type
for(int i = 0; i < nrows; i++){ //fill the entire board with pieces
for(int j = 0; j < ncols; j++){
(*board)[i][j] = (struct cell){ 0, 0 };
}
}
}

Variable array size in c

I'm trying to declare arrays with a variable size, given by user input.
So far I have something like this:
typedef struct _object{
int rowsAmount;
int columsAmount;
int* rows;
int* colums;
} object;
object* newObject(int ra, int ca){
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->rows = [ra];
o->colums = [ca];
return o;
}
int main(){
newObject(3,4);
}
I expected this wouldn't work, but I want something like this, and I don't know how to do it.
It looks like you're basically implementing a dynamic Matrix object here. You want something like:
typedef struct _object{
int rowsAmount;
int columsAmount;
int* matrix;
int** rows;
} object;
object* newObject(int ra, int ca){
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->matrix = malloc(ra * ca * sizeof(int));
o->rows = malloc(ra * sizeof(int*));
for (size_t i = 0; i != ra; ++i) o->rows[i] = o->matrix + (i * ca);
return o;
}
You should also create a destructor function destroyObject, which similarly frees all the memory allocated for o and o->matrix.
Edit:
However, your comment that:
"I'm just trying to learn c, this is only about the setting the size.
I just happened to try it with 2 arrays"
...makes this question somewhat confusing, because it indicates you are not, in fact, trying to create a matrix (2D array) despite your use of "row"/"column" terminology here, but that you simply want to understand how to dynamically allocate arrays in C.
If that's the case, an array in C is dynamically allocated using a pointer variable and malloc:
size_t array_size = 10; /* can be provided by user input */
int* array = malloc(sizeof(int) * array_size);
And then later, the dynamically-allocated array must be freed once you are finished working with it:
free(array);
To dynamically allocate a 2d array of data in C:
Allocate the memory for the entire data. That memory is pointed to by arrayData.
Allocate an 1D Array of pointers one for each row
Point those pointers to the memory address corresponding each row
Code:
int *arrayData = malloc(sizeof(int) * rows * columns);
int **array = malloc(sizeof(int*) * rows);
for(int i=0; i < rows;++i){
array[i] = arrayData + i * columns;
}
You can now access the memory as array[row][col].
You can create a array with size input from user with out a structure.
int *array1;
int size;
// get input from user
array1 = malloc(sizeof(int)*size);
// do your stuff
free(array1);
if you want a 2D array,
int **array2;
int row, col;
int i;
array2 = malloc(sizeof(int*)*row);
for(i=0;i<row;++i)
array2[i] = malloc(sizeof(int)*col);
//use the array
for(i=0;i<row;++i)
free(array2[i]);
free(array2);
if you really need a structure array, then allocate memory for it in your newObject() function
typedef struct _object{
int rowsAmount;
int columsAmount;
int** array;
//int* colums;
} object;
object* newObject(int ra, int ca){
int i;
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->array = malloc(sizeof(int*)*ra);
for(i=0;i<ra;i++)
o-<array[i]=malloc(sizeof(int)*ca);
return o;
}
int main(){
newObject(3,4);
}
I think that quite often people use dynamic memory allocation when scoped variables can be used instead. For example, array sized from user's input can be allocated on stack without using malloc/free:
int array_size;
scanf("%d", &array_size);
if (array_size > 0) {
/* Allocate array on stack */
float array[array_size];
/* ... do smth with array ... */
}
/* Out of scope, no need to free array */
Of course if your data block is huge, heap memory is a must, but for small allocations scopes are just fine.
Easiest way is to use boost::multi_array
Not only will you get any number of dimensions, it's also stored very efficiently as a single contiguous block of memory rather than n dimensional array.
CPU's are designed to traverse arrays quickly, and you could potentially utilise caching/prefetch/pipelining features of the compiler using this.
Eg
// 2 dimensions
int xDim;
int yDim;
cin >> xDim; // From user..
cin >> yDim;
// Initialise array
boost::multi_array<int,2> my2dgrid(boost::extents[xDim][yDim]);
// Iterate through rows/colums
for(int j = 0 ; j < yDim-1; j++) { // Row traversal
for(int i = 0 ; i < xDim-1; i++) { // Column traversal
int value = grid[j][i]; // Get a value
grid[j][i] = 123; // set a value
// Do something...
}
#include <stdio.h>
#include <stdlib.h>
typedef struct _object{
int rowsAmount;
int columsAmount;
int **rows;
// int* colums;
} object;
object* newObject(int ra, int ca){
int r;
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->rows = (int **)malloc(ra*sizeof(int *));
for(r=0;r<ra;++r)
o->rows[r] = (int*)malloc(ca*sizeof(int));
return o;
}
int main(){
object *obj= newObject(3,4);
obj->rows[2][3]=5;
return 0;
}

Random matrix struct creation

I'm trying to make a struct that generates a random matrix and am getting "error: expected â=â, â,â, â;â, âasmâ or â_attribute_â before âmatrixâ" when compiling. How can I get this to work effectively and efficiently?
I guess expected errors usually are caused by typos but I don't see any.
I'm very new to C so pointers and malloc are quite foreign to me. I really appreciate your help.
/* It's called RandomMatrixMaker.c */
#include <stdio.h>
#include <stdlib.h>
typdef struct {
char* name;
int MID;
int MRows;
int MCols;
long[][]* MSpace;
} matrix;
matrix makeRIDMatrix(char* name, int MID, int MRows, int MCols) {
matrix m;
static int i, j, r;
m.name = name;
m.MID = MID;
m.MRows = MRows;
m.MCols = MCols;
for (i=0; i<m.MRows; i++) {
for (j=0; i<m.MCols; j++) {
r = random(101);
*(m.MSpace[i][j]) = r;
}
}
return m;
}
int main(void) {
makeRIDMatrix("test", 1, 10, 10);
return 0;
}
There is indeed a typo. You misspelled typedef:
typdef struct {
should be:
typedef struct {
EDIT:
Also, there's no reason to use static here:
static int i, j, r;
You can just get rid of the static modifier.
int i, j, r;
As another poster mentioned, there's a typo, but even with that corrected, it wouldn't compile, due to the definition of matrix.MSpace.
Let's begin in makeRIDMatrix(). You've declared an automatic (stack) variable of type "matrix". At the end of the function, you return that object. Whilst this is permissible, it's not advisable. If the struct is large, you will be copying a lot of data unnecessarily. Better to pass a pointer to a matrix into makeRIDMatrix(), and have makeRIDMatrix() fill in the contents.
The test in the inner loop is against i, but should be against j.
Next, let's look at the definition of "matrix". The definition of "MSpace" is a mess, and wouldn't even compile. Even if it did, because you haven't defined the length of a row, the compiler would not be able to calcuate the offset to any given item in the array. You want a two-dimensional array without giving the row length, but you can't do that in C. You can in other languages, but not C.
There's a lot more I could point out, but I'd be missing the real point. The real point is this:
C Is Not Java.
(It's also not one of the interpreted languages such as JavaScript, PHP, Python, Ruby and so on.)
You don't get dynamically-expanding arrays; you don't get automatic allocation of memory; you don't get garbage collection of unreferenced memory.
What you need is something more like this:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct {
char* name;
int MID;
unsigned int MRows;
unsigned int MCols;
long *MSpace;
} matrix;
void makeRIDMatrix(matrix *pmx, char* name, int MID,
unsigned int MRows, unsigned int MCols) {
int i, j;
long *MSpace = malloc(sizeof(*MSpace)*MRows*MCols);
if (MSpace == NULL) {
return;
}
pmx->name = name;
pmx->MID = MID;
pmx->MRows = MRows;
pmx->MCols = MCols;
pmx->MSpace = MSpace;
srandom((unsigned int)time(NULL));
for (i=0; i<MRows; i++) {
for (j=0; i<MCols; j++) {
long int r = random() % 101L;
*(MSpace++) = r;
}
}
}
inline long * item_addr(const matrix *pmx,
unsigned int row, unsigned int col) {
if (pmx == NULL || pmx->MSpace == NULL
|| row >= pmx->MRows || col >= pmx->MCols) {
return NULL;
}
return &(pmx->MSpace[row * pmx->MCols + col]);
}
long get_item(const matrix *pmx, unsigned int row, unsigned int col) {
long *addr = item_addr(pmx, row, col);
return addr == NULL ? 0L : *addr;
}
void set_item(matrix *pmx,
unsigned int row, unsigned int col,
long val) {
long *addr = item_addr(pmx, row, col);
if (addr != NULL) {
*addr = val;
}
}
int main(void) {
matrix m;
makeRIDMatrix(&m, "test", 1, 10, 10);
return 0;
}
Note a few things here. Firstly, for efficiency, I fill the array as if it were one-dimensional. All subsequent get/set of array items should be done through the getter/setter functions, for safety.
Secondly, a hidden nasty: makeRIDMatrix() has used malloc() to allocate the memory - but it's going to be job of the calling function (or its successors) explciitly to free() the allocated pointer when it's finished with.
Thirdly, I've changed the rows/cols variables to unsigned int - there's little sense in definining an array with negative indices!
Fourthly: little error checking. For example, makeRIDMatrix() neither knows nor cares whether the parameter values are sensible (e.g. the matrix pointer isn't checked for NULLness). That's an exercise for the student.
Fifthly, I've fixed your random number usage - after a fashion. Another exercise for the student: why is the way I did it not good practice?
However - all of this is moot. You need to get yourself a good C textbook, or a good online course, and work through the examples. The code you've given here shows that you're punching above your weight at the moment, and you need to develop some more C muscles before going into that ring!
In relation to your question about "variable sized arrays", you could have something like:
/* can stick this into your struct, this is just an example */
size_t rows, cols;
long **matrix;
/* set the values of rows, cols */
/* create the "array" of rows (array of pointers to longs) */
matrix = (long**)malloc(rows * sizeof(long*));
/* create the array of columns (array of longs at each row) */
for (i = 0; i < rows; i++)
matrix[i] = (long*)malloc(cols * sizeof(long));
/* ... */
/* free the memory at the end */
for (i = 0; i < rows; i++)
free(matrix[i]);
free(matrix);
Then you can just access the dynamically allocated matrix similar to any other array of arrays.
ie. to set element at the first row (row 0) and fourth column (column 3) to 5:
matrix[0][3] = 5;

2d array in C with negative indices

I am writing a C-program where I need 2D-arrays (dynamically allocated) with negative indices or where the index does not start at zero. So for an array[i][j] the row-index i should take values from e.g. 1 to 3 and the column-index j should take values from e.g. -1 to 9.
For this purpose I created the following program, here the variable columns_start is set to zero, so just the row-index is shifted and this works really fine.
But when I assign other values than zero to the variable columns_start, I get the message (from valgrind) that the command "free(array[i]);" is invalid.
So my questions are:
Why it is invalid to free the memory that I allocated just before?
How do I have to modify my program to shift the column-index?
Thank you for your help.
#include <stdio.h>
#include <stdlib.h>
main()
{
int **array, **array2;
int rows_end, rows_start, columns_end, columns_start, i, j;
rows_start = 1;
rows_end = 3;
columns_start = 0;
columns_end = 9;
array = malloc((rows_end-rows_start+1) * sizeof(int *));
for(i = 0; i <= (rows_end-rows_start); i++) {
array[i] = malloc((columns_end-columns_start+1) * sizeof(int));
}
array2 = array-rows_start; //shifting row-index
for(i = rows_start; i <= rows_end; i++) {
array2[i] = array[i-rows_start]-columns_start; //shifting column-index
}
for(i = rows_start; i <= rows_end; i++) {
for(j = columns_start; j <= columns_end; j++) {
array2[i][j] = i+j; //writing stuff into array
printf("%i %i %d\n",i, j, array2[i][j]);
}
}
for(i = 0; i <= (rows_end-rows_start); i++) {
free(array[i]);
}
free(array);
}
When you shift column indexes, you assign new values to original array of columns: in
array2[i] = array[i-rows_start]-columns_start;
array2[i] and array[i=rows_start] are the same memory cell as array2 is initialized with array-rows_start.
So deallocation of memory requires reverse shift. Try the following:
free(array[i] + columns_start);
IMHO, such modification of array indexes gives no benefit, while complicating program logic and leading to errors. Try to modify indexes on the fly in single loop.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int a[] = { -1, 41, 42, 43 };
int *b;//you will always read the data via this pointer
b = &a[1];// 1 is becoming the "zero pivot"
printf("zero: %d\n", b[0]);
printf("-1: %d\n", b[-1]);
return EXIT_SUCCESS;
}
If you don't need just a contiguous block, then you may be better off with hash tables instead.
As far as I can see, your free and malloc looks good. But your shifting doesn't make sense. Why don't you just add an offset in your array instead of using array2:
int maxNegValue = 10;
int myNegValue = -6;
array[x][myNegValue+maxNegValue] = ...;
this way, you're always in the positive range.
For malloc: you acquire (maxNegValue + maxPosValue) * sizeof(...)
Ok I understand now, that you need free(array.. + offset); even using your shifting stuff.. that's probably not what you want. If you don't need a very fast implementation I'd suggest to use a struct containing the offset and an array. Then create a function having this struct and x/y as arguments to allow access to the array.
I don't know why valgrind would complain about that free statement, but there seems to be a lot of pointer juggling going on so it doesn't surprise me that you get this problem in the first place. For instance, one thing which caught my eye is:
array2 = array-rows_start;
This will make array2[0] dereference memory which you didn't allocate. I fear it's just a matter of time until you get the offset calcuations wrong and run into this problem.
One one comment you wrote
but im my program I need a lot of these arrays with all different beginning indices, so I hope to find a more elegant solution instead of defining two offsets for every array.
I think I'd hide all this in a matrix helper struct (+ functions) so that you don't have to clutter your code with all the offsets. Consider this in some matrix.h header:
struct matrix; /* opaque type */
/* Allocates a matrix with the given dimensions, sample invocation might be:
*
* struct matrix *m;
* matrix_alloc( &m, -2, 14, -9, 33 );
*/
void matrix_alloc( struct matrix **m, int minRow, int maxRow, int minCol, int maxCol );
/* Releases resources allocated by the given matrix, e.g.:
*
* struct matrix *m;
* ...
* matrix_free( m );
*/
void matrix_free( struct matrix *m );
/* Get/Set the value of some elment in the matrix; takes logicaly (potentially negative)
* coordinates and translates them to zero-based coordinates internally, e.g.:
*
* struct matrix *m;
* ...
* int val = matrix_get( m, 9, -7 );
*/
int matrix_get( struct matrix *m, int row, int col );
void matrix_set( struct matrix *m, int row, int col, int val );
And here's how an implementation might look like (this would be matrix.c):
struct matrix {
int minRow, maxRow, minCol, maxCol;
int **elem;
};
void matrix_alloc( struct matrix **m, int minCol, int maxCol, int minRow, int maxRow ) {
int numRows = maxRow - minRow;
int numCols = maxCol - minCol;
*m = malloc( sizeof( struct matrix ) );
*elem = malloc( numRows * sizeof( *elem ) );
for ( int i = 0; i < numRows; ++i )
*elem = malloc( numCols * sizeof( int ) );
/* setting other fields of the matrix omitted for brevity */
}
void matrix_free( struct matrix *m ) {
/* omitted for brevity */
}
int matrix_get( struct matrix *m, int col, int row ) {
return m->elem[row - m->minRow][col - m->minCol];
}
void matrix_set( struct matrix *m, int col, int row, int val ) {
m->elem[row - m->minRow][col - m->minCol] = val;
}
This way you only need to get this stuff right once, in a central place. The rest of your program doesn't have to deal with raw arrays but rather the struct matrix type.

Resources