为什么在C中打开/写入大量文件失败?

时间:2014-02-28 13:39:03

标签: c printf

我想写一个由C程序打开的1000000个文本文件。在循环中,我调用它在文本文件中写入的函数。文本文件先前已创建。该程序只能打开508个文本文件并写入其中。为什么呢?

代码是:

int main()
{
    char* s[1000000];

    for(i = 0; i < 1000000; i++)
    {
        /* Initialize s[i] */
        export( s[i] );
    }
}

static int export( char* filename )
{
    FILE* file;
    int i, j, d;

    file = fopen( filename, "w+" );

    if( ! ( file ) )
    {
        fprintf( stderr, "Warning: error opening %s, %s, line %d in export",
        filename, __FILE__, __LINE__ );
        return 1;
    }
    d = feat[0].d;

    fprintf( file, "%d %d\n", n, d );

    for( i = 0; i < n; i++ )
    {
        fprintf( file, "%f %f %f %f", feat[i].y, feat[i].x,
        feat[i].scl, feat[i].ori );

        for( j = 0; j < d; j++ )
        {
            /* write 20 descriptor values per line */
            if( j % 20 == 0 )
            fprintf( file, "\n" );
            fprintf( file, " %d", (int)(feat[i].des[j]) );
        }
        fprintf( file, "\n" );
    }

    if( fclose(file) )
    {
        fprintf( stderr, "Warning: file close error, %s, line %d\n",
        __FILE__, __LINE__ );
        return 1;
    }
    return 0;
}

此代码完美适用于508个第一个文本文件,然后我得到无法打开下一个文件的异常错误。

2 个答案:

答案 0 :(得分:2)

您似乎使用了一堆未初始化的字符指针作为文件名;将其中一个解释为无效的文件名并不奇怪。这是未定义的行为,除非您实际将s初始化为某些内容。

预先分配文件名数组似乎很奇怪;你一次只需要一个,为什么要浪费大量的记忆呢?

你应该做的事情如下:

for(i = 0; i < 1000000; ++i)
{
  char filename[64];
  sprintf(filename, "file-%d", i);
  export(filename);
}

这会生成file-0file-1等文件名。

答案 1 :(得分:2)

如果在处理508文件后出现错误,我怀疑你遇到了同时打开文件数量的实现限制。如果是这种情况,那么写完后每个文件都应fclose(fp)。 (对于stdout,stdin,stderr,508为511减3)。

请注意,C标准仅保证您可以同时打开FOPEN_MAX(stdio.h)文件,这可能低至8。

或者你可能遇到其他限制,例如超出磁盘配额或设备上没有剩余空间?有什么特别的错误?当fopen,fprintf或fclose失败时,添加对perror()的调用。

我们在使用时看到你的export()函数完全吗?或者你是否将其剥离以显示逻辑?如果是后者,请查找fopen / fclose之后的早期return语句。早期返回可能会导致我们称之为资源泄漏(类似于内存泄漏,但此处泄漏的资源是文件描述符/流)。