Estoy escribiendo un código que necesita leer fasta files, por lo que parte de mi código (incluido a continuación) es un analizador de Fasta. Como una sola secuencia puede abarcar varias líneas en formato fasta, necesito concatenar varias líneas sucesivas leídas del archivo en una sola cadena. Hago esto, reasignando el búfer de cadena después de leer cada línea, para ser la longitud actual de la secuencia más la longitud de la línea leída adentro. Hago algunas otras cosas, como quitar el espacio en blanco, etc. Todo va bien para el primera secuencia, pero los archivos fasta pueden contener múltiples secuencias. De manera similar, tengo una matriz dinámica de estructuras con dos cadenas (título y secuencia real), que es "char *". De nuevo, cuando encuentro un nuevo título (introducido por una línea que comienza con '>') incremento el número de secuencias y realococo el buffer de la lista de secuencias. Los segfaults REALLOC sobre la asignación de espacio para la segunda secuencia conUso de realloc para expandir el búfer al leer el archivo falla
*** glibc detected *** ./stackoverflow: malloc(): memory corruption: 0x09fd9210 ***
Aborted
Porque la vida de mí no puedo ver por qué. Me he encontrado a través del BGF y todo parece estar funcionando (es decir, todo lo que es inicializado, los valores parece cuerdo) ... Aquí está el código:
#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;
}
Gracias por todos los comentarios sobre la rutina subserie. Lo he arreglado en mi código. También noté que la forma en que manejaba los índices negativos era incorrecta. Debería agregar el índice negativo, no restarlo. Dicho esto, también me di cuenta de que copié la función substr por error, ya que no la llamo en el resto del código pegado. – sirlark
'strip()' también tiene errores. Hará cosas malas con cadenas de longitud cero. Parece que no lo llamas así, pero creo que sería bueno solucionarlo cuando se use en otro lugar. –