1

我试图从实际的角度了解如何考虑内存分配。我想我理解如何实现malloc,并且realloc在基本意义上,但我不明白如何有效地做到这一点。

我的书籍和在线参考资料中的示例都显示realloc在循环中使用,例如增加数组的长度。我不太清楚,但似乎这种方法可能不是很有效。

例如,在下面的测试代码中,正在构建一个 JSON 字符串以将文件名、大小和上次修改日期传递给另一个应用程序。事先不知道目录中有多少文件或数据元素的大小。我意识到这很简单,但是当事先不知道行数及其大小时,我在构建 SQLite 结果行的 JSON 字符串时遇到了类似的问题。这个文件信息代码示例更容易理解,但更重要的任务是 SQLite 数据。

在下面的代码中,将一段 JSON 的开头写入字符数组json,然后在循环中写入每段文件信息,然后while关闭 JSON 字符串。全部使用snprintf.

现在,json任意设置为长度1000;并且代码确实会生成此数据的正确格式的 JSON 字符串,只要它适合。

我的问题是,是否realloc()真的应该在循环的每次迭代中使用while来扩展json一旦知道要写入的下一个数据的大小的大小?或者,realloc()有点工作,最好在开始时分配一个更大的内存块,然后在剩余空间json达到最小值或snprintf返回一个指示写入截断的值时用另一个更大的块扩展它,这样来电少了realloc()

这在“现实生活”中是如何做到的,而不是在书中举例说明?

谢谢你。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>

void read_dir_1 ( char *, char * );

int main( void )
  {
    read_dir_1( "c", "./SQLite3/" );
    return 0;
  }

void read_dir_1 ( char *ext, char *path )
{
  DIR *dp;
  struct dirent *ep;
  struct stat info;
  int rc, q, i, l;
  char *t;
  char fl_name[ 400 ]; 
  char json[ 1000 ]; // Temporary value.

  dp = opendir( path );

  if ( dp != NULL )
    {
      i = 0;
      q = 0;   
      l = sizeof( json ) - 1;
      // Open the JSON string.
      q = snprintf( json, l, "%s", "{\"c\":\"A\",\"d\":[" );
      l -= q;
      i += q;

      while ( ep = readdir( dp ) )
        {
          rc = snprintf( fl_name,
                         sizeof( fl_name ) - 1,
                         "%s%s",
                         path,
                         ep->d_name
                        );

          if ( ( rc = stat( fl_name, &info ) ) != 0 )
             {
               printf( "rc : %d\n", rc );
               printf( "errno : %d, strerror : %s\n", errno, strerror( errno ) );
               continue;
             }

          if ( ( info.st_mode & S_IFMT ) != S_IFREG ) 
            continue;

          t = strrchr( ep->d_name, '.' ); 
          if ( !t || strcmp( ++t, ext ) != 0 ) continue;

          q = snprintf( json + i,
                        l,
                        "%s%.*s%s%d%s%d%s",   
                        "{\"n\":\"",
                        strlen( ep->d_name ) - strlen( ext ) - 1, ep->d_name,
                        "\",\"s\":",
                        info.st_size / 1024,
                        ",\"d\":",
                        info.st_mtime,
                        "}," );                   

          if ( q < 0  || q > l )
            {
              // Ran out of room in json to hold the file info.
              printf( "Ran out of memory to store file info." );
              //?????????? Better free all allocated memory before returning.
              return;
            }
          i += q;
          l -= q;
        } // next while loop

      // Close the JSON string. Overwrite the comma after the last object in the array "d".
      q = snprintf( json + i - 1,
                    l,
                    "%s",
                    "]}" );                   
    
      if ( q < 0  || q > l )
        {
          // Ran out of room in json to hold the file info.
          printf( "Ran out of memory to store file info." );
          //?????????? Better free all allocated memory before returning.
          return;
        }

      printf( "JSON : %s", json );
      closedir (dp);
    }
  else
    {
      perror ("Couldn't open the directory");
    }

  //?????????? Better free all allocated memory before returning.
  return;
}
4

0 回答 0