大家好,我是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);
答案 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
,则在发生错误之前,标准输出可能不会发送到控制台。显然,如果您使用调试器,您将确切知道发生了段错误。
查看您的代码时,nR
和nC
未定义,因此我不知道rankMat
和srcMat
有多大,但我想到了两个想法看着你的代码:
i
和j
,以确保它们不超过nR
和nC
nR
和nC
足够大,则可能意味着您在堆栈中使用了大量内存(srcMat
,rankMat
,{{ 1}},normMat
都很大。我不知道你在运行什么环境,但有些系统我无法处理大量的堆栈(Linux,Windows等应该没问题,但我做了很多嵌入式工作)。我通常在堆中分配非常大的结构(使用sorts
)。