-3

I am writing some code in C to read some file data in arrays and keep getting a segmentation fault compiling with gcc. It reads the file up to 11th line of data then gives the fault. Been through some other similar questions on here but can't find a solution. Thanks

code:

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

int ainb(char a[],char b[])//returns 0 if str b contains a returns 1 otherwise
{
    int i=0,j0=-1,j1=0,count=0;
    if(strlen(b)<strlen(a)) {return 1;}
    for(i=0;i<strlen(b);i++) {
        if((b[i]==a[j1])&&(j1==j0+1)){
            j0=j1;j1++;
        } else {
            j0=-1;j1=0;
        }
        if((j1+1)==strlen(a)) {break;}
    }
    if((j1+1)==strlen(a)){
        return 0;
    } else {
        return 1;
    }
}

void read_pdb(FILE* fp,char **atm,int *atnum,char **name,char **res,char *chain,int *resnum,double *x,double *y,double *z,double *occ,double *bfac,char **elem,double ac[2][3])  //reads file lines and stores in arrays
{
    printf("\nReading pdb data\n");
    int i=0,j=0;
    char buff[7];
    fpos_t position;

    while(!feof(fp))
    {

        fgetpos(fp,&position);fgets(buff,sizeof buff,fp);
        if((ainb("ATOM",buff)==0)||(ainb("HETATM",buff)==0))
        {
            fsetpos(fp,&position);printf("\ngetting position %d\n",i+1);
            fscanf(fp,"%6s%5d %4s %3s %1s%4d %8lf%8lf%8lf%6lf%6lf %2s \n",atm[i],&atnum[i],name[i],res[i],&chain[i],&resnum[i],&x[i],&y[i],&z[i],&occ[i],&bfac[i],elem[i]);
            printf("\nnode %d data found\n",i+1);
            printf("\n%6s%5d %4s %3s %1s%4d    %8.3lf%8.3lf%8.3lf%6.2lf%6.2lf          %2s  \n",atm[i],atnum[i],name[i],res[i],&chain[i],resnum[i],x[i],y[i],z[i],occ[i],bfac[i],elem[i]);
            if(ainb("HETATM",atm[i])==0){
                ac[j][0]=x[i];ac[j][1]=y[i];ac[j][2]=z[i];j++;
            }
            i++;
        }
    }
    printf("\n%d Atoms read\n",i);
}

void main()
{
    double ac[2][3];
    int N,k;

    double *x,*y,*z,*occ,*bfac;
    char **atm,**name,**res,**elem,*chain;
    int *atnum,*resnum;
    FILE *out;

    out=fopen("OUT.pdb","r");//something to check for file
    N=66;

    //make dynamic arrays
    x=(double*)malloc(N*sizeof(double));
    y=(double*)malloc(N*sizeof(double));
    z=(double*)malloc(N*sizeof(double));
    occ=(double*)malloc(N*sizeof(double));
    bfac=(double*)malloc(N*sizeof(double));
    atnum=(int*)malloc(N*sizeof(int));
    resnum=(int*)malloc(N*sizeof(int));
    atm=(char**)malloc(N*sizeof(char));
    name=(char**)malloc(N*sizeof(char));
    res=(char**)malloc(N*sizeof(char));
    elem=(char**)malloc(N*sizeof(char));
    chain=(char*)malloc(N*sizeof(char));
    for(k=0;k<N;k++)
    {
        atm[k]=(char*)malloc(7*sizeof(char));
        name[k]=(char*)malloc(5*sizeof(char));
        res[k]=(char*)malloc(4*sizeof(char));
        elem[k]=(char*)malloc(3*sizeof(char));
    }
    //read in data
    read_pdb(out,atm,atnum,name,res,chain,resnum,x,y,z,occ,bfac,elem,ac);
    fclose(out);

    printf("\n-------------------------------------------\nTest Complete\n");
    free(x);
    free(y);
    free(z);
    free(occ);
    free(bfac);
    free(elem);
    free(name);
    free(atm);
    free(res);
    free(resnum);
    free(atnum);
    free(chain);
}

The output is:

Reading pdb data

getting position 1

node 1 data found

  ATOM    1   CA PRO A   1       4.612   0.903   5.089  1.00 24.97           C  

getting position 2

node 2 data found

  ATOM    2   CA SER A   2       3.526   0.341   3.809  1.00 59.99           C  

getting position 3

node 3 data found

  ATOM    3   CA ARG A   3       6.208   1.550   6.551  1.00 20.40           C  

getting position 4

node 4 data found

  ATOM    4   CA TRP A   4       5.912   2.348   4.388  1.00 50.28           C  

getting position 5

node 5 data found

  ATOM    5   CA GLE A   5       4.087   4.359   6.884  1.00 54.04           C  

getting position 6

node 6 data found

  ATOM    6   CA THR A   6       4.405   1.292   2.566  1.00 62.06           C  

getting position 7

node 7 data found

  ATOM    7   CA TYR A   7       3.327   3.041   5.205  1.00 50.46           C  

getting position 8

node 8 data found

  ATOM    8   CA VAL A   8       5.276   0.109   0.387  1.00 58.00           C  

getting position 9

node 9 data found

  ATOM    9   CA LEU A   9       2.992   3.190   3.084  1.00 41.48           C  

getting position 10

node 10 data found

  ATOM   10   CA CYS A  10       3.565   0.287   0.721  1.00 47.65           C  

getting position 11
Segmentation fault (core dumped)
dbush
  • 205,898
  • 23
  • 218
  • 273
lsaw
  • 1
  • 1
  • So, what does the 11th line of your file look like? Does it have one? Also, you should really check the return from `fscanf()` to make sure it successfully read all the fields. – Dmitri Jul 14 '15 at 18:38
  • 11th line is: ATOM 11 CA VAL A 11 4.835 4.291 0.185 1.00 38.80 C – lsaw Jul 14 '15 at 18:42
  • just put in a check and returns 12, as expected, until it gives the fault – lsaw Jul 14 '15 at 18:48
  • Side note: [Do not cast return value of malloc](http://stackoverflow.com/q/605845/4185106). – moffeltje Jul 14 '15 at 19:01

2 Answers2

1

Lets consider this code:

name=(char**)malloc(N*sizeof(char));
for(k=0;k<N;k++)
{
    name[k]=(char*)malloc(5*sizeof(char));
}

You allocate n*sizeof(char) array and try to store N pointers to char in it. But size of pointer to the char is greater than sizeof(char), so you get buffer overflow and undefined behavior even on the initialization stage. You are lucky and your program is not crashing at this stage, but it will fail on the array usage. To prevent this error you should use sizeof(char*) in your allocation code.

Ari0nhh
  • 5,720
  • 3
  • 28
  • 33
0

Rather than hard code the type, and get it wrong for name, let the compiler figure it out. Less code, easier to read and easier to code & maintain.

//bfac=(double*)malloc(N*sizeof(double));
//resnum=(int*)malloc(N*sizeof(int));
//name=(char**)malloc(N*sizeof(char));  OP was looking for `sizeof (char*)`

bfac   = malloc(N * sizeof *bfac);
resnum = malloc(N * sizeof *resnum);
name   = malloc(N * sizeof *name);

Also in C, no need to cast the result of malloc().

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256