2012-03-16 81 views
1

我一直在努力解决这个问题,但无济于事。在下面的代码中,我使用了一个char指针(all_seq),但是当我释放它时,在代码结束时,有时会出现段错误。我有时会说,因为它显然取决于输入文件。用一个小的输入文件,没关系。有一个大的,这也很好。对于中等大小的文件,它会出现段错误。我只是想不出为什么...由于释放内存导致的分段错误

任何想法将不胜感激。谢谢。

/* SeqProb (Sequence Probability) - 2012/03/13 */ 
/* Given a series of aligned sequences -in one file, one per line- this program calculates the probability of having, in each location, the letter in the first sequence. */ 

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

FILE *input_file; 
FILE *output_file; 

/////////////////////////////// 
// DECLARATION OF FUNCTIONS: // 
/////////////////////////////// 
int GetSize(FILE *file, int *length, int *lines); 
double CalcProb(char *one_seq); 

////////////////////////////////////////////////////////////////// 
// ************************************************************ // 
// **************  START MAIN BLOCK  ************** // 
// ************************************************************ // 
////////////////////////////////////////////////////////////////// 

int main(int argc, char *argv[]) // We expect three command-line arguments: 1)program name, 2)file to read and 3)file to write. 
{ 
    int i=0,j=0; 
    int length, lines, size; 
    double prob=0; 
    char *all_seq, *one_seq; 

//////////////////////////// 
// CHECK INPUT ARGUMENTS: // 
//////////////////////////// 
// Check if arguments in command line are right and if file can be opened for reading: 

    if (argc != 3) { // There should be 3 arguments for correct execution 
     printf("\n Usage: %s <input file> <output file>\n\n ", argv[0]); // We print argv[0] assuming it is the program name 
     exit(1); 
    } 

    if (!(input_file=fopen(argv[1],"r"))){ 
     printf("\n Error: can't open input file \n\n"); 
     exit(2); 
    } 

    if (!(output_file=fopen(argv[2],"w"))){ 
     printf("\n Error: can't open output file \n\n"); 
     exit(3); 
    } 

///////////////////////////////////////// 
// GET LENGTH AND NUMBER OF SEQUENCES: // 
///////////////////////////////////////// 
    GetSize(input_file,&length,&lines); 
    size=length*lines; 
    printf("\n length of sequences = %d\n",length); 
    printf(" number of sequences = %d\n",lines); 

////////////////////////////////////////////////////// 
// ALLOCATE MEMORY FOR all_seq AND one_seq VECTORS: // 
////////////////////////////////////////////////////// 
    all_seq = (char *) malloc((length*lines+10)*sizeof(char)); 
    one_seq = (char *) malloc((lines+10)*sizeof(char)); 
    if (all_seq == NULL){ // In case of memory allocation failure, exit. 
     printf ("Error: Can't allocate memory \n"); 
     exit(4); 
    } 
    if (one_seq == NULL){ // In case of memory allocation failure, exit. 
     printf ("Error: Can't allocate memory \n"); 
     exit(5); 
    } 

///////////////////////////////////////////// 
// INITIALIZE VECTORS all_seq and one_seq: // 
///////////////////////////////////////////// 
    for (i=0;i<=size;i++) { 
     all_seq[i]=0; 
    } 
    for (i=0;i<=length;i++) { 
     one_seq[i]=0; 
    } 

/////////////////////////////////////////////////////// 
// LOAD SEQUENCES FROM INPUT FILE IN VECTOR all_seq: // 
/////////////////////////////////////////////////////// 
// Read input file, containing sequences, and put every letter into the all_seq vector, one sequence right after the other (we'll also include the escape character (\n) at the end of each line). 
// Note that, in this way, the letter at location (row,col) in the input file will be given by all_seq[(length+1)*row+col]: 
    printf("\n Processing file: %s\n\n", argv[1]); 
    rewind(input_file); 
    for (i=0; i<=size; ++i) { 
     fscanf(input_file,"%c",&all_seq[i]); 
//  printf("%d: %c\n",i, all_seq[i]); 
    } 
// printf("%c",all_seq[2]); 

/////////////////////////////////////////////////////////////// 
// CALCUALTE PROBABILITIES OF EACH LETTER IN FIRST SEQUENCE: // 
/////////////////////////////////////////////////////////////// 
// Read one column at a time, write it to the one_seq vetor, and calculate the probability of occurrance of the first letter in that column; repeat for all columns: 
    for (j=0; j<length; j++) { 
     for (i=0; i<lines; i++) { 
     one_seq[i]=all_seq[(length+1)*i+j]; 
     } 
     prob = CalcProb(one_seq); 
//  printf("col=%d: prob=%f \n\n",j,prob); 
// Write output file: the first column is just an enumeration, from 1 to the length of the sequences, and the second column gives the probability for finding the first letter in the column, anywhere along the column (a measure of its conservation). 
     fprintf(output_file,"%d  %f\n",j+1,prob); 
    } 

//////////////////////////////////// 
/// CLOSE FILES AND FREE MEMORY: /// 
//////////////////////////////////// 
    fclose(input_file); 
    fclose(output_file); 
    free(all_seq); 
    free(one_seq); 
    return(0); 
} 
////////////////////////////////////////////////////////////////// 
// ************************************************************ // 
// ***************  END MAIN BLOCK  *************** // 
// ************************************************************ // 
////////////////////////////////////////////////////////////////// 

////////////////////////////////////////////////////// 
// FUNCTION GetSize: LENGTH AND NUMBER OF SEQUENCES // 
////////////////////////////////////////////////////// 
int GetSize(FILE *file, int *length, int *lines) 
{  
    char c; 
    int i=0; 
    int *len; 
// Count how many characters in first line: 
    while ((c=fgetc(file)) != '\n') { 
    ++i; 
    } 
    *length=i; 
    *lines=0; 
    *len=0; 

// Now count many lines, and check that all lines have same length: 
    i=0; 
    rewind(file); 
    while ((c=fgetc(file)) != EOF) { 
     ++i; 
     if (c=='\n') { 
     *lines=*lines+1; 
     *len=i-1; 
     i=0; 
//  printf("length=%d\n",*len); 
     if (*len != *length && *len != 0) { 
      printf("ERROR: not all lines in input file have the same length.\n"); 
      exit(6); 
     } 
     if (*len == 0) { 
      *lines=*lines-1; 
     } 
     } 
    } 

// printf("lines=%d\n",*lines); 
    return(0); 
} 

/////////////////////////////////////////////////////////////////////////////// 
// FUNCTION CalcProb: PROBABILITY OF THE FIRST CHARACTER IN THE GIVEN VECTOR // 
/////////////////////////////////////////////////////////////////////////////// 
double CalcProb(char *one_seq) 
{ 
    int i=0; 
    double count=0, prob=0; 
    while (one_seq[i] != '\0') { 
//  printf("one_seq[%d]= %d\n",i,one_seq[i]); 
    if (toupper(one_seq[i]) == toupper(one_seq[0])) { 
     count=count+1; 
    } 
    i=i+1; 
    } 
    prob=count/i; 
// printf("count=%f, i=%d, prob=%f: \n",count,i,prob); 
    return(prob); 
} 
+0

'sizeof(char)'将始终返回1,因此这是无用的乘法操作FYI 您是否尝试过通过valgrind运行它? – 2012-03-16 20:08:24

+0

'one_seq'被归零为'length',但它是基于'lines'分配的。 – Andrei 2012-03-16 20:11:38

+0

@ 0A0D - 这是不正确的。 sizeof(char)在你使用过的每个系统上可能都是1,但是确实存在不是这种情况的系统(主要是DSP处理器),如果你想编写可移植的代码,你不能做出这样的假设 - 尤其是当编译器/优化器可能将其转化为编译时决策时,最终无需付出任何代价。 – mah 2012-03-16 20:11:48

回答

5
在释放内存

错误通常通过释放同一指针两次(不太可能在这里),(收到块)释放无效指针,或先前缓存欠载(同一块的)或溢出引起导致管理数据被破坏。既然你说它发生在大文件作为输入而不是小文件,你很可能超过了缓冲区。

当您只分配lines元素时,它看起来像是在0和length之间迭代,从而超出one_seq []。

还请注意,您应该能够放弃您的+10安全区域,并且您还应该修复您的for循环为<最后一个索引,而不是<=

+0

是的,你是对的!问题是一个小错误:我为one_seq的长度“lines”分配空间,但之后我将其初始化为“length”,该长度可能比“lines”大,因而超出了它的范围。 – user1274826 2012-03-16 20:26:24