简体   繁体   中英

Pointers in C - “Segmentation Fault” when structuring matrix

I am using Eclipse on a 32-bit Ubuntu virtual machine to work on a project. I have a big problem when trying to implement a structure or just when trying to run a specific function. The function is this one:

int count (matrix m, int v[], int w[], int col) {

    int r=0;
    int j=0;

    while (j < m.length) {
        int k=0;
        bool aux=true;

        while (k < col && aux ){
            if (v[k] == 1) {
                if(m.i[j][k] != w[k])
                    aux=false;
            }
            k++;
        }

        if(aux) r++;
        j++;
    }
    return r;
}

This function receives a matrix (defined below), a vector with ones and zeros (to learn which columns to search, a vector with the values we want to search in those columns and also the number of columns (equal to the length of the vectors and matrix). When it strikes the second "if" it gives me Segmentation Fault (I cannot understand what it is), and I can see that it is not correct to define it that way, but I have tried and tried and I can't seem to find a way to access the values in the vector. Here follows my struct matrix:

typedef int *ind; 

struct matrix { 
    ind *i;
    int length;
};
typedef struct matrix matrix;

In this structure my matrix has a pointer and the length (number of lines); the pointer goes to a vector of pointers (one pointer for each line) and each one of those pointers go to a vector that is, in fact, my line of the matrix. Here go my functions to add and create an empty matrix:

matrix emptyS(int n, int col) {
matrix m;
int d=0;
m.length=0;
m.i=(ind*) malloc(sizeof(int)*n);
int x;
    for (x=0; x < n; x++)
           {
               *m.i = (int*) malloc(sizeof(int)*col);
           }
while (d<n){
    m.i[d]=NULL;
    d++;
}
return m;
} /*Updated*/

matrix add(matrix m,int v[]){
    m.i[m.length+1]=v;
    m.length++;
    return m;
}

I know this is a very specific question but I have been going crazy changing my functions and cannot seem to be successful.

Your definition of i is this:

 ind *i;

You have the following definition of ind :

typedef int* ind;

This means that your definition of i really is this:

int ** i;

Which is a pointer to a pointer, this means you have to allocated your memory incorrectly.

m.i=(ind*) malloc(sizeof(int)*n); 

This allocation is only for a int* , but what about the second pointer? You've never allocated any memory for it!

Allocate the rows of the matrix, something like this:

for (int x = 0; x < nofrows; x++)
   { 
       *m.i = (int*)malloc(sizeof(int)); 
   }

EDIT

Your code after you do your allocation for your matrix, sets your pointers in the matrix to NULL , essentially leaving all the memory you just allocated dangling , with nothing pointing to it !!

while (d<n){
    m.i[d]=NULL; <--- LEAVES YOUR MEMORY JUST ALLOCATED FOR ROW d DANGLING.
    d++;
}

You should not set it to NULL , but instead you should write stuff in your matrix you just allocated memory for.

Replace the line

m.i=(ind*) malloc(sizeof(int)*n);

by

m.i=(ind*) malloc(sizeof(ind)*n);

I hope this helps.

#include <stdlib.h>
#include <stdio.h>

typedef enum{false,true}  bool;

typedef struct matrix_ {
    int **rows;
    unsigned size ;
    unsigned used ;
} matrix;

unsigned count (matrix m, int v[], int w[], unsigned ncol) {
    unsigned cnt=0;
    unsigned j=0;

    for (j=0; j < m.used; j++) {
        unsigned k;
        bool aux=true;

        for (k=0;k < ncol && aux; k++ ){
            if (v[k] == 1  && m.rows[j][k] != w[k]) {
                    aux=false;
            }
        }

        if(aux) cnt++;
    }
    return cnt;
}
#define barf(s) do { \
    fprintf (stderr, "%s\n", s); \
    exit (EXIT_FAILURE); \
    } while(0)

matrix emptyS(unsigned siz) {
    matrix m;
    unsigned d;

    m.used=0;
    m.size = siz;
    m.rows = malloc(siz * sizeof *m.rows );

    for (d=0; d<siz; d++){
        m.rows[d]=NULL;
    }
    return m;
}

matrix add(matrix m,int v[]){
    if (m.used >= m.size) barf("Danger, Bill Robinson!" );
    m.rows[m.used++]=v;
    return m;
}
int main(void)
{
int a[] = { 0,1,0};
int b[] = { 0,1,1};
int c[] = { 0,0,0};
int v[] = { 1,0,1};
int w[] = { 0,1,0};
matrix mymatrix;
unsigned zcount;

mymatrix = emptyS(3);
mymatrix = add( mymatrix, a);
mymatrix = add( mymatrix, b);
mymatrix = add( mymatrix, c);

zcount = count(mymatrix, v, w, 3);

printf("Count = %u\n", zcount);

return 0;
}

A few 'stylistic' hints:

  • for-loops are less error-prone than while() loops, and save two lines.
  • for counts and indices, unsigned types are less error-prone. (there is only one corner case)
  • Don't hide pointers inside typedefs; it will confuse yourself and others.
  • Don't cast malloc()s return value; it is not needed and may suppress error messages.
  • ptr = malloc (n * sizeof *ptr) is more stable WRT typo's and future edits.
  • if you allocate a varable sized object (such as your matrix) store the size (number of elements) inside that object. An object should be "self-contained".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM