将FILE类型的数组传递给function = Segmentation fault

时间:2015-10-25 23:53:02

标签: c gcc

以下代码将指向FILE类型的数组的指针传递给函数,在访问数组时导致分段错误(gcc,在Ubuntu 12.04 LTS上)。

在main中,请输入以下代码:

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

FILE **ptr_rdfile;

//Function declares
FILE ** open_files(int argc, char *argv[]);
int parse_files(FILE **ptr_rdfile[], int argc, char *argv[]);

//check for required input
if( argc < 2 )
   {
   printf( "Error - must enter at least one binary filename to read in.\n" );
   return 1;
   }

if( argc > 5 )
   {
   printf( "Error - maximum number of binary filenames %d.\n", MAX_FILES );
   return 1;
   }

//open files specified on cmd line
ptr_rdfile = open_files(argc, argv);
if( ptr_rdfile == NULL ) 
  {
  printf( "Exiting program\n" );
  return 1;
  }

//parse file contents into corresponding array of structs, print to stdout
  if( parse_files(&ptr_rdfile, argc, argv) !=0 )
    {
    printf( "Parse Failed - Exiting program\n" );
    return 1;
}

函数open_files如下:

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

FILE ** open_files(int argc, char *argv[])
  {
  int i;
  FILE **ptr_rdfile;

  ptr_rdfile = malloc( sizeof(FILE *) * (argc-1));

  if( ptr_rdfile == NULL )
    {
    printf("Error: Not enough memory\n");
    getchar();
    return NULL;
    } 

  i=1;
  for( i=1; i<argc; i++)
    {    
    errno=0;
    ptr_rdfile[i-1] = fopen(argv[i],"rb");
    //printf( "ptr_rdfile[%d]:%p\n", (i-1), ptr_rdfile[i-1]);
    if (!ptr_rdfile[i-1])
      {
      printf( "Unable to open file - is file name correct???   Errno = %d,  %s.\n", errno, strerror(errno) );
      return NULL;
      }
    } 

  return ptr_rdfile;
  }

函数parse_files如下:

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

int parse_files(FILE **ptr_rdfile[], int argc, char *argv[])
  {
  unsigned int j;
  signed int i;

  struct prod_rec
    {
    int ver;
    char type_code[20];
    unsigned int unit_ID;   
    float price;
    };

  struct prod_rec prod[argc];

  i=0;
  for( i=0; i<argc-1; i++)
    { 
    //printf( "fread: i = %d", i );
    if (fread(&prod[i], sizeof(struct prod_rec), 1, *ptr_rdfile[i]) != 1) 
      {
      printf( "error writing sturct:  Errno = %d,  %s.\n", errno, strerror(errno) );
      }
    }
}

在调用parse_file之前在main中运行以下printf(以及各种迭代),

printf( "parse_files: ptr_rdfile = %p\n *ptr_rdfile = %p\n ptr_rdfile[0] = %p\n ptr_rdfile[1] = %p\n (void*)&ptr_rdfile[0] = %p\n (void*)&ptr_rdfile[1] = %p\n *ptr_rdfile[0] = %p\n *ptr_rdfile[1] = %p\n, **ptr_rdfile = %p\n **ptr_rdfile[1] = %p\n", ptr_rdfile, *ptr_rdfile, ptr_rdfile[0], ptr_rdfile[1], (void*)&ptr_rdfile[0], (void*)&ptr_rdfile[1], *ptr_rdfile[0], *ptr_rdfile[1], **ptr_rdfile, **ptr_rdfile );

显示以下内容:

 ptr_rdfile = 0x804c008
 *ptr_rdfile = 0x804c018
 ptr_rdfile[0] = 0x804c018
 ptr_rdfile[1] = 0x804c180
 (void*)&ptr_rdfile[0] = 0x804c008
 (void*)&ptr_rdfile[1] = 0x804c00c

从main导入parse_files,使用gdb,ptr_rdfile具有以下内容:

(gdb) print ptr_rdfile[1]
$1 = (FILE **) 0xb7e52e55
(gdb) print *ptr_rdfile
$2 = (FILE **) 0x804c008
(gdb) print **ptr_rdfile
$3 = (FILE *) 0x804c018
(gdb) print ***ptr_rdfile
$4 = {_flags = -72539000, ...    
print *ptr_rdfile[1]
$11 = (FILE *) 0x5b18c483

除了我在上面的颠簸之外,我认为ptr_rdfile [0]似乎是好的,但不是ptr_rdfile [1]。

我还为ptr_rdfile尝试了以下格式:

//function declare:
  int parse_files(FILE ***ptr_rdfile, int argc, char *argv[]);
function call:
  if( parse_files(&ptr_rdfile, argc, argv) !=0 )

上面导致同样的错误。

在我将上面的代码移到parse_files之前,我在main中使用了该代码,并且它与ptr_rdfile的相同声明一起正常工作,并且以下调用fread:

if (fread(&prod[i], sizeof(struct prod_rec), 1, ptr_rdfile[i]) != 1) 

转到单独的功能,基于我在本网站上研究过的讨论。将指针数组传递给函数,我就完成了上述尝试,但我显然在这里遗漏了一些东西......

任何调试建议都表示赞赏。

谢谢。

更新: 我尝试了类似@ user3629249建议的内容,这导致了以下编译警告:

$ gcc -g -Wall -Wextra -o parsebin.out open_files.c parse_files.c parsebin.c
parsebin.c: In function ‘main’:
parsebin.c:41:3: warning: passing argument 1 of ‘parse_files’ from incompatible pointer type [enabled by default]
parsebin.c:17:7: note: expected ‘struct FILE **’ but argument is of type ‘struct FILE ***’

我刚刚尝试使用以下代码(func declare,func call和function code):

主要:

//func declare:
int parse_files(FILE **ptr_myfile, int argc, char *argv[]);

//func call:
if( parse_files(ptr_myfile, argc, argv) !=0 )

在parse_files中:

int parse_files(FILE **ptr_myfile, int argc, char *argv[])
  {
  ...
   if (fread(&prod[i], sizeof(struct prod_rec), 1, ptr_myfile[i]) != 1) 

嗯,当然,我必须在之前的尝试中搞砸了一些东西,因为上面似乎工作正常。哇,谢谢user3629249和其他所有人的亲切帮助和指导。在这个帮助下,我想我理解这里的指针方案。再次感谢你。

0 个答案:

没有答案