我是一个从遥远的过去生锈的吱吱作响的C程序员。拥有打开二进制文件的代码(包含有关产品的详细信息,例如ID,价格等)。调用.out程序时文件名是输入参数(当前在Ubuntu 12.04 w / gcc上运行)。编译没有错误。运行时,文件被打开,数据被转换为结构(与二进制文件中的数据字段匹配),以简单的列方式打印所有数据字段(没有花哨的格式,只是列的东西,每列对应于每个文件包含在命令行中)。然后通过fclose关闭文件指针。在测试中,一切正常,直到fclose。最后一个fclose(最后一个文件指针关闭)导致分段错误。运行gdb(例如,有4个输入文件),当第四个文件指针试图fclose时输出以下内容:
编程接收信号SIGSEGV,分段故障。 0xb7e95ac6在? ()来自/lib/i386-linux-gnu/libc.so.6
文件指针被设置为文件指针数组,如下所示:
FILE **ptr_myfile;
ptr_myfile = malloc( sizeof(FILE *) * (argc-1));
if( ptr_myfile == NULL )
{
printf("Error: Not enough memory\n");
getchar();
return 1;
}
i=1;
for( i=1; i<argc; i++)
{
errno=0;
ptr_myfile[i-1] = fopen(argv[i],"rb");
printf( "ptr_myfile: i-1 = %d\n", i-1 );
if (!ptr_myfile[i-1])
{
printf( "Unable to open file - is file name correct??? Errno = %d, %s.\n", errno, strerror(errno) );
return 1;
}
}
这是因为输入的文件数量因用户的需要而异。
接下来,将文件读入结构:
i=0;
for( i=0; i<argc-1; i++)
{
if (fread(&prod[i], sizeof(struct prod_rec), 1, ptr_myfile[i]) != 1)
{
printf( "error writing sturct: Errno = %d, %s.\n", errno, strerror(errno) );
}
}
接下来,解析并打印结构的内容(除非认为有必要解决此问题,否则我不会在此处包含该代码...)。但是,使用sprintf将每行打印输出(std out)构建到malloc&#39; d char数组中,每个文件的相应结构成员(两个for循环 - 每行为外部,每个文件为内部&# 39; s数据)。得到的数组完全按照需要打印到输出。
显示数据后,执行以下代码以关闭文件:
i=0;
for( i=0; i<(argc-1); i++)
//for( i=0; i<4; i++)
{
if ( ptr_myfile[i] )
{
fclose( ptr_myfile[i] );
printf( "fclosed i = %d\n", i );
}
}
在最后一次通过上述for循环期间(例如,有4个输入文件,它将在i = 3的传递中),发生分段错误。因此上面循环中的诊断printf显示:
fclosed i = 0
fclosed i = 1
fclosed i = 2
分段错误(核心转储)
整个下午都在搜索/阅读fclose,分段错误。我没看到问题可能是什么。我对gdb不太称职 - 关于如何调试和解释gdb可能提供的任何建议,真的很感激。显然,我做的很愚蠢,但没有看到它。谢谢。
更新: 在两个有用的建议之后,将问题隔离到创建第一行打印输出的代码段,这是一个标题行。代码:
unsigned int field_size=20;
char* print_line = (char*) malloc( (argc)*field_size*sizeof(char) );
char* field = (char*) malloc( field_size*sizeof(char) );
//heading row corresponding to number of input files
j=1;
for( j=1; j<(argc); j++)
{
sprintf( field, "%-20s", argv[j] ); //string to add to first line
strcat(print_line, field); //add string to first line
}
出现的问题在于如何构建要打印的每行输出 - 我使用了strcat。然而,刚才注意到,strcat似乎需要一个指向char字符串的const指针,我不认为我在做。 &#39; strcat(print_line,field)&#39;设置&quot; print_line&#39;保持所有输入文件名字符串出现在输出到stdout的第一行(通过printf)。 &#39; field&#39;,生成为,&#39; sprintf(字段,&#34;% - 20s&#34;,argv [j])&#39;,将每个打开的文件的文件名保存到在印刷输出的第一行。 (我没有得到关于const char *违反的编译警告或运行时错误 - 应该有这种用法吗?)。试图找出另一种方法来做这个没有strcat,或相反,以某种方式使'&#39;字段&#39;是一个const * char。建议?再次感谢你。
第二次更新:问题解决了。 谢谢你。有关为字符串结尾字符分配空间的指导。由于我为每个字段分配了比实际填充argv中的字符更多的空间,所以我滑倒了,所以我假设了。我认为&#f; sprintf(字段,&#34;% - 20s&#34;,argv [j])&#39;甚至每个&#39; argv [j]&#39;包含少于20个字符,&#34;% - 20s&#34;插入20个字符(空格字符填充空格)然后插入字符串结尾,我没有分配。至少那是我在这一点上的分析(请在这里纠正我......)。谢谢你们。 (我需要关闭/结束这个讨论页面吗?)