fopen大文件上的Segfault错误

时间:2011-07-18 17:36:09

标签: c segmentation-fault fopen

大家好,我是C的新手,但最近我的fopen出现了一个奇怪的段错误。

   FILE* thefile = fopen(argv[1],"r");

我遇到的问题是这个代码适用于其他较小的文本文件,但是当我尝试使用大约400MB的文件时,它会产生一个sefault错误。我甚至尝试过硬编码文件名,但这也不起作用。在其余代码中是否会出现问题导致此行上的段错误?(怀疑它但想知道它是否可能。对于一个小文本文件没有错误,但是一个大文本文件真的很奇怪确实会出错。

谢谢!

EDIT *不想让这种情况陷入困境,但是我的代码是

int main(int argc, char *argv[])
{
 if(argc != 3)
{
printf("[ERROR] Invalid number of arguments. Please pass 2 arguments, input_bound_file (column  1:probe, columne 2,...: samples) and desired_output_file_name");
exit(2);
}

int i,j;
rankAvg= g_hash_table_new(g_direct_hash, g_direct_equal);
rankCnt= g_hash_table_new(g_direct_hash, g_direct_equal);
table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
getCounts(argv[1]);
printf("NC=: %i       nR =: %i",nC,nR);
double srcMat[nR][nC];
int rankMat[nR][nC];
double normMat[nR][nC];
int sorts[nR][nC];
char line[100];

FILE* thefile = fopen(argv[1],"r");
printf("%s\n", strerror(errno));
FILE* output = fopen(argv[2],"w");
char* rownames[100];
i=0;j = 1;
int processedProbeNumber = 0;
int previousStamp = 0;
fgets(line,sizeof(line),thefile); //read file

while(fgets(line,sizeof(line),thefile) != NULL)
{
cleanSpace(line); //creates only one space between entries
  char dest[100];
  int len = strlen(line);
  for(i = 0; i < len; i++)
  {
    if(line[i] == ' ') //read in rownames
    {
    rownames[j] = strncpy(dest, line, i);
    dest[i] = '\0';
    break;
    }
  }

  char* token = strtok(line, " ");
  token = strtok(NULL, " ");
  i=1;

  while(token!=NULL) //put words into array
    {
    rankMat[j][i]= abs(atof(token));
      srcMat[j][i] = abs(atof(token));
    token = strtok(NULL, " ");
    i++;
    }

    // set the first column as a row id
    j++;
  processedProbeNumber++;

    if( (processedProbeNumber-previousStamp) >= 10000)
    {
      previousStamp = processedProbeNumber;
      printf("\tnumber of loaded lines = %i",processedProbeNumber);

    }
}
printf("\ttotal number of loaded lines  = %i \n",processedProbeNumber);
fclose(thefile);

3 个答案:

答案 0 :(得分:1)

现在不应该将400Mb视为“大文件”。我会为大于2Gb的文件保留这个。

此外,只打开一个文件不太可能产生段错误。您是否向我们展示了访问该文件的代码?我怀疑其他一些因素在这里发挥作用。

更新

我仍然无法确切地知道这里发生了什么。有些奇怪的事情可能是合法的:你丢弃第一行以及每行的第一个标记。

您还为所有rownames[j](第一个除外)分配dest的地址,rownames[j]是一个具有块范围的变量,其相关内存最有可能在该块之外重用。我希望你不要依赖{{1}}有意义(但为什么你有它们?)你永远不会尝试访问它们。

C99允许您将变量声明与实际指令混合,但我建议进行一些清理以使代码更清晰(同样更好的缩进也会有帮助)。

根据症状,我会在某处寻找一些内存损坏。在小文件(因此较少的令牌)上,它可能会被忽视,但是对于较大的文件(以及更多令牌),它会触发段错误。

答案 1 :(得分:1)

一般来说,2GB(2 ** 31)或更大的文件是您可以获得的文件。这是因为对于像文件索引这样的东西,你开始用32位整数的空间耗尽,并且通常在相对偏移量的方向上占用一位。

据说在Linux上,您可以使用以下宏定义解决此问题:

#define _FILE_OFFSET_BITS 64

某些系统还为大型文件打开提供单独的API调用(例如:MKS中的fopen64())。

答案 2 :(得分:1)

你怎么知道fopen是错误的?如果您只是在代码中添加printf,则在发生错误之前,标准输出可能不会发送到控制台。显然,如果您使用调试器,您将确切知道发生了段错误。

查看您的代码时,nRnC未定义,因此我不知道rankMatsrcMat有多大,但我想到了两个想法看着你的代码:

  • 您不会检查ij,以确保它们不超过nRnC
  • 如果nRnC足够大,则可能意味着您在堆栈中使用了大量内存(srcMatrankMat,{{ 1}},normMat都很大。我不知道你在运行什么环境,但有些系统我无法处理大量的堆栈(Linux,Windows等应该没问题,但我做了很多嵌入式工作)。我通常在堆中分配非常大的结构(使用sorts)。