gpt4 book ai didi

c - 移动 stderr fd 指针开始

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:18:44 24 4
gpt4 key购买 nike

我正在编写一个包装器,它 fork 一个 execv() 进程。子项的输出在 stderr 中捕获。当 waitpid() 释放时,我可以读取 stderr 的内容并报告回来。

在我的例子中,我想动态分配一个缓冲区并将 stderr 写入此缓冲区。

为了调整缓冲区的大小,我可以使用 realloc(),但这不是很有效,而且我发现它往往会膨胀内存池的使用。相反,我想知道大小而不改变它的指针。

考虑以下内容,并注意 MyStderr 只是 stderr 的占位符:

int size=0;
int ch=0;
// int MyStderr is the stderr fd
FILE *nCountFD = fdopen(MyStderr, "r");
while ((ch = getc(nCountFD)!=EOF)
{
++size;
}
printf("Size is %ld\n", size);

在这里我得到了尺寸。但是,现在 MyStderr 的文件指针位于其缓冲区的末尾。

我尝试使用 lseek

lseek()stderr 失败,所以我不能在这里使用它。至少,这是我的测试和 stackoverflow 搜索所表明的。

所以...

  1. 有没有办法在不将 MyStderr 移动到 eof 的情况下获取大小?

  1. 是否有 lseek 方法可以与 MyStderr 一起使用?

注意。这是我能想到的唯一解决方案,使用 realloc..

char *buf=(char*)malloc(80);
char *NewBuf=NULL;
int n=80;
while ((ch = getc(nCountFD)!=EOF)
{
buf[i]=ch;
++size;
if (size>n)
{
n=n+80;
NewBuf= realloc(buf, n);
// some code to make sure it works here //
buf=NewBuf;
}
}
printf("Size is %ld\n", size);

现在更新

我决定让我的结果缓冲区的初始 malloc 足够大,以便在大多数情况下不太可能使用 realloc(),而不是构建功能来解决 stderr 是无缓冲的这一事实。如果发生 realloc(),则按照建议,每个 realloc() 的原始分配大小都会加倍。

在测试(100000 次迭代)中,这非常有效,没有泄漏或明显的膨胀。

我非常感谢 Stack Overflow 社区。谢谢大家。

下面的代码不会独立运行。它放在这里是为了说明我做了什么。

..在解析命令行、 fork 、执行 execv 和清理的所有代码之后...

while (waitpid(nPID, &status, 0) != nPID)
;
i = 0;
nFD = fdopen(nErrFD, "r");
if (!nFD) {
snprintf(cErrMsg, 80, "Cannot open fd[%i]. Failed to spaw process",
nErrFD);
cbuf = strcpy(cbuf, cErrMsg);
goto NECerror;
}

close(nErrFD);


cbuf = calloc(nBufSz, sizeof(char));
memset(cbuf, 0x00, nBufSz);
i = 0;
while ((ch = getc(nFD)) != EOF) {
cbuf[i] = (char) ch;
++size;
++i;
if (size > nBufSz) {
nBufSz = nBufSz + nBaseBufSz;
NewBuf = realloc(cbuf, nBufSz);
if (NewBuf == NULL) {
snprintf(cErrMsg, 80,
"Internal error:cannot allocate [%i] bytes", nBufSz);
cbuf = strcpy(cbuf, cErrMsg);
fclose(nFD);
goto NECerror;
}
cbuf = NewBuf;
free(NewBuf);
}

}
fclose(nFD);

最佳答案

管道是不可搜索的——如果您正在从另一个进程提供的管道中读取数据,那么您将无法搜索其数据流。您必须在读取时存储数据。

您可能会看到大量内存抖动的原因是您扩展缓冲区的方式——每次超出缓冲区时,您只能将其扩展一个常数。如果在超过时加倍它的大小,您将获得更好的成功:这是dynamic arrays 的众所周知的技术。 .

例如:

// Error checking omitted for expository purposes
size_t size = 4096;
char *buf = malloc(size);
char *bufPtr = buf;
ssize_t n;
while((n = read(MyStderr, bufPtr, 4096) > 0)
{
bufPtr += n;

// Make sure we always have at least 4096 bytes of free space in the
// buffer for the next read
if(size - (bufPtr - buf) < 4096)
{
size *= 2; // Watch out for overflow!
buf = realloc(buf, size);
}
}

// The (bufPtr - buf) bytes of buf now hold the entirety of the process's stderr

关于c - 移动 stderr fd 指针开始,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9197443/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com