Объяснение переполнения стека при использовании чтения небольшого файла и сомнительный обходной путь
-
06-07-2019 - |
Вопрос
Надеюсь, вопрос объяснил мою проблему.Я также был бы признателен, если бы был объяснен обходной путь, который «работает».
Традиционный способ чтения файла (который я знаю)
int fd;
char buffer[MAX];
while(read(fd,buffer,MAX)>0)
{
buffer[MAX]='\0';
write(sockfd,buffer,MAX);
memset(buffer,NULL,MAX);
}
вызывало переполнение.Обходной путь, который каким-то образом неожиданно сработал, был
while((read(fd,buffer,MAX)!=0)||(read(fd,buffer,MAX)!= -1))
{
buffer[MAX]='\0';
write(sockfd,buffer,MAX);
memset(buffer,NULL,MAX);
}
^^ Этот код распечатывает весь файл, без пропусков, насколько это заметно.
Вещи как
do
{
int temp;
temp=read(fd,buffer,MAX);
if((temp == 0) || (temp == -1))
{
break;
}
buffer[MAX]='\0';
write(sockfd,buffer,MAX);
memset(buffer,NULL,MAX);
}while(1);
также вызвало переполнение стека.Я упускаю здесь что-то действительно важное?
Спасибо
Решение
Почему вы говорите, что это вызывает переполнение?
Обратите внимание, что read()
не буду писать \0
в конце char
массив, поэтому, если вы сделаете что-то вроде printf("%s", buffer)
скорее всего, это потерпит неудачу, потому что printf
будет ожидать строку, завершающуюся NUL.Возможно, вы захотите прочитать MAX-1
и установить buffer[number_of_read_characters] = '\0'
где число_прочитанных_символов это что угодно read()
возвращается, если положительный.
Также обратите внимание, что когда вы объявляете char buffer[MAX]
, поскольку в C индексация начинается с нуля, наивысший buffer
индекс MAX-1
, поэтому, когда вы настраиваете buffer[MAX]='\0'
вы уже вышли за пределы своего массива.
Другие советы
Одна проблема:
buffer[MAX]='\0';
шагов в стеке, так как наивысший действительный индекс для массива размера MAX равен MAX-1 (из-за индексов, отсчитываемых от 0).
Возвращаемое значение -1 из read указывает на ошибку, поэтому правильно проверять read() > 0.Более того, обычное возвращаемое значение чтения — это количество прочитанных байтов, а чтение не гарантирует никакого 0-завершения.вам нужно сделать что-то в духе
while (bytesRead=read() > 0) {
write(buffer, bytesRead);
...
Глядя на код, я бы предположил, что это потому, что логика другая.
В примере, который работает, read(fd,buffer,MAX)
метод выполняется дважды.
Подумайте об этом так:
while (dosomething() != 0 || dosomething() != -1)
{
// some work
}
Этот цикл будет бесконечным, если метод dosomething() является идемпотентным, однако, если первый раз, когда вы запускаете его в операторе while, отличается от второго, он прервется.
Это объясняет, чем отличается путь выполнения, но я не могу понять, почему первый вариант переполняется...Я подумаю об этом и обновлю.(или нет - кажется, на него ответили!)
Попробуй это:
int fd, readCharacter;
char buffer[MAX];
while( readCharacter = read(fd, buffer, MAX**-1**) > 0 )
{
buffer[readCharacter] = '\0';
// ...
}