我试图从实际的角度了解如何考虑内存分配。我想我理解如何实现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;
}