Sto scrivendo del codice che deve leggere fasta files, quindi parte del mio codice (incluso sotto) è un parser fasta. Poiché una singola sequenza può estendersi su più righe nel formato fasta, ho bisogno di concatenare più righe successive lette dal file in una singola stringa. Lo faccio, riallocando il buffer delle stringhe dopo aver letto ogni riga, per essere la lunghezza corrente della sequenza più la lunghezza della riga letta. Faccio qualche altra cosa, come lo spoglio dello spazio bianco ecc. Tutto va bene per il prima sequenza, ma i file fasta possono contenere più sequenze. Allo stesso modo, ho una matrice dinamica di strutture con due stringhe (titolo e sequenza effettiva), essendo "char *". Di nuovo, mentre incontro un nuovo titolo (introdotto da una riga che inizia con '>') incremento il numero di sequenze e rialloco il buffer dell'elenco di sequenze. Il realloc segfaults sull'allocazione dello spazio per la seconda sequenza conUtilizzo di realloc per espandere il buffer durante la lettura dal file si blocca
*** glibc detected *** ./stackoverflow: malloc(): memory corruption: 0x09fd9210 ***
Aborted
Per la vita di me non riesco a capire perché. Ho eseguito attraverso gdb e tutto sembra funzionare (cioè tutto viene inizializzata, i valori sembrano sani di mente) ... Ecco il codice:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <errno.h>
//a struture to keep a record of sequences read in from file, and their titles
typedef struct {
char *title;
char *sequence;
} sequence_rec;
//string convenience functions
//checks whether a string consists entirely of white space
int empty(const char *s) {
int i;
i = 0;
while (s[i] != 0) {
if (!isspace(s[i])) return 0;
i++;
}
return 1;
}
//substr allocates and returns a new string which is a substring of s from i to
//j exclusive, where i < j; If i or j are negative they refer to distance from
//the end of the s
char *substr(const char *s, int i, int j) {
char *ret;
if (i < 0) i = strlen(s)-i;
if (j < 0) j = strlen(s)-j;
ret = malloc(j-i+1);
strncpy(ret,s,j-i);
return ret;
}
//strips white space from either end of the string
void strip(char **s) {
int i, j, len;
char *tmp = *s;
len = strlen(*s);
i = 0;
while ((isspace(*(*s+i)))&&(i < len)) {
i++;
}
j = strlen(*s)-1;
while ((isspace(*(*s+j)))&&(j > 0)) {
j--;
}
*s = strndup(*s+i, j-i);
free(tmp);
}
int main(int argc, char**argv) {
sequence_rec *sequences = NULL;
FILE *f = NULL;
char *line = NULL;
size_t linelen;
int rcount;
int numsequences = 0;
f = fopen(argv[1], "r");
if (f == NULL) {
fprintf(stderr, "Error opening %s: %s\n", argv[1], strerror(errno));
return EXIT_FAILURE;
}
rcount = getline(&line, &linelen, f);
while (rcount != -1) {
while (empty(line)) rcount = getline(&line, &linelen, f);
if (line[0] != '>') {
fprintf(stderr,"Sequence input not in valid fasta format\n");
return EXIT_FAILURE;
}
numsequences++;
sequences = realloc(sequences,sizeof(sequence_rec)*numsequences);
sequences[numsequences-1].title = strdup(line+1); strip(&sequences[numsequences-1].title);
rcount = getline(&line, &linelen, f);
sequences[numsequences-1].sequence = malloc(1); sequences[numsequences-1].sequence[0] = 0;
while ((!empty(line))&&(line[0] != '>')) {
strip(&line);
sequences[numsequences-1].sequence = realloc(sequences[numsequences-1].sequence, strlen(sequences[numsequences-1].sequence)+strlen(line)+1);
strcat(sequences[numsequences-1].sequence,line);
rcount = getline(&line, &linelen, f);
}
}
return EXIT_SUCCESS;
}
Grazie per tutti i commenti sulla routine di sottostringa. L'ho risolto nel mio codice. Ho notato anche che il modo in cui gestivo gli indici negativi era sbagliato. Dovrei aggiungere l'indice negativo, non sottrarlo. Detto questo, ho anche realizzato che ho copiato la funzione substr in errore, poiché non la chiamo nel resto del codice incollato. – sirlark
'strip()' è anche bacato. Farà cose cattive con stringhe di lunghezza zero. Sembra che tu non lo chiami con tali stringhe, ma penso che sarebbe una buona cosa da sistemare quando è usato altrove. –