Я пишу оболочку, которая разветвляется на 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
, поэтому я не могу использовать его здесь.По крайней мере, это то, что показывает мой тестирование и поиск в стеке.
Итак ...
- Есть ли способ получить размер, не перемещая
MyStderr
в eof?
или
- Существует ли метод
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);
А теперь обновление
Вместо того, чтобы создавать функциональность, чтобы обойти тот факт, что stderrбез буферизации, я решил сделать начальный malloc моего буфера результатов достаточно большим, чтобы realloc () была маловероятной в большинстве случаев.И если происходит realloc (), первоначальное распределение удваивается по размеру для каждого realloc (), как предложено.
В тестировании (100000 итераций) это работает очень хорошо, без утечек или заметных вздутий.
Я многим обязан сообществу переполнения стека.Спасибо всем.
Приведенный ниже код не будет работать автономно.Это помещено здесь, чтобы проиллюстрировать, что я сделал.
.. после всего кода, который анализирует командную строку, разветвляется, выполняет 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);