将大量xml文件转换为文本时出现分段错误

时间:2013-03-22 18:55:43

标签: c xml linux

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

int main()
{
  FILE *fin,*fout;
  char dest[80]="/home/vivs/InexCorpusText/";
  char file[30];
  DIR *dir;
  char c,state='1';
  int len;
  struct dirent *ent;
  if((dir=opendir("/home/vivs/InexCorpus"))!=NULL)
  {
    while((ent=readdir(dir))!=NULL)
    {
      if(strcmp(ent->d_name,".") &&
         strcmp(ent->d_name,"..") &&
         strcmp(ent->d_name,".directory"))
      {
        len=strlen(ent->d_name);
        strcpy(file,ent->d_name);
        file[len-3]=file[len-1]='t';
        file[len-2]='x';
        //strcat(source,ent->d_name);
        strcat(dest,file);
        printf("%s\t%s\n",ent->d_name,dest);
        fin=fopen(ent->d_name,"r");
        fout=fopen(dest,"w");
        while((c=fgetc(fin))!=EOF)
        {
          if(c=='<')
          {
            fputc(' ',fout);
            state='0';
          }
          else if(c=='>')
            state='1';
          else if(state=='1')
          {
            if(c!='\n')
            fputc(c,fout);
            if(c=='.')
            {
              c=fgetc(fin);
              if(c==' '||c=='\n'||c=='<')
              {
                fputc('\n',fout);
                ungetc(c,fin);
              }
              else fputc(c,fout);
            }
          }
        }
      }
      close(fin);
      close(fout);
      strcpy(dest,"/home/vivs/InexCorpusText/");
    }
    closedir(dir);
  }
  else
  {
    printf("Error in opening directory\n");
  }
  return 0;
}

我试图将xml文件转换为文本。此代码只删除标签,没有别的。 当我为大约300个文件执行此代码时,它不显示任何错误,但当数量达到500或更多时,我在处理大约300个文件后收到分段错误。

3 个答案:

答案 0 :(得分:2)

至少有一个'从一开始就'的原因:

这是来自男人的struct dirent声明:

   On Linux, the dirent structure is defined as follows:

       struct dirent {
           ino_t          d_ino;       /* inode number */
           off_t          d_off;       /* offset to the next dirent */
           unsigned short d_reclen;    /* length of this record */
           unsigned char  d_type;      /* type of file; not supported
                                          by all file system types */
           char           d_name[256]; /* filename */
       };

你在任何超过30(实际上是29)字符的名字上遇到麻烦。发生内存覆盖是因为 file 只有30个字节('\ 0'终结符保留1):

char file[30];
...
strcpy(file,ent->d_name);

答案 1 :(得分:1)

XML中有两种结构,它们不会出现在您的帐户中。

  1. 属性内容可以包含未转义的>个字符,这些字符可能会丢失您的计数。请参阅http://www.w3.org/TR/REC-xml/#NT-AttValue

  2. CDATA部分可以包含<>个字符作为文字文本,只要它们不会显示为结束]]>字符串的一部分。见http://www.w3.org/TR/REC-xml/#NT-CharData。这可能会严重破坏你的逻辑。

  3. 为什么不查看文件以查看是否包含文本CDATA

    您可能需要考虑使用xsltproc or libxslt;一个非常简单的XSLT转换将为您提供您想要的。有关此类转换引擎,请参阅Extract part of an XML file as plain text using XSLT

答案 2 :(得分:0)

好的,另一个有问题的地方:

len=strlen(ent->d_name);
....
file[len-3]=file[len-1]='t';
file[len-2]='x';

因为d_name可能少于3个字符,所以它可能再次导致内存覆盖。 您应该对strlen()之类的函数小心,并始终验证其结果。