LINUX.ORG.RU

[grammar^Wspecifications nazi] POSIX & return codes


0

0

Upon successful completion, socket() shall return a non-negative integer, the socket file descriptor. Otherwise, a value of -1 shall be returned and errno set to indicate the error.

(c) IEEE 1003.1

Собственно вопрос: а чисто теоретически, может ли функция вернуть отрицательное значение отличное от (-1)? Это считается ошибкой или валидным дескриптором?

И как правильнее проверять на ошибку в таких случаях:

if (ret_code == -1)
{
    /* ... handle error ... */
}
или
if (ret_code < 0)
{
    /* ... handle error ... */
}
?

Deleted

В стандарте написанное -1, значит -1, если не вылезет чего ещё. :)

Как правило в таких случаях рекмоендуется сравнивать именно со значением, заявленным в стандарте, т.е. с -1.

shty ★★★★★
()
Ответ на: комментарий от shty

>> Как правило в таких случаях рекмоендуется сравнивать именно со значением, заявленным в стандарте, т.е. с -1.

Дак в том то и фокус, что в стандарте написано:

а) При нормальном заврешении выдаётся положительное число.
б) При ошибке выдаётся (-1).

А остальные отрицательные значения int как-то выпали из стандарта...

Deleted
()
Ответ на: комментарий от Deleted

> А остальные отрицательные значения int как-то выпали из стандарта...

ну они не то что выпали, скорее, "поведение непредсказуемо". исходя из базового принципа "всё, что не оговорено - запрещено". с практической же точки зрения, кто-то сравнивает с -1 а кто-то <0. оба варианта имеют право на существование и я не слышал, чтобы первый вызывал какие то реальные проблемы.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от Deleted

>Дак в том то и фокус, что в стандарте написано:

>а) При нормальном заврешении выдаётся положительное число.

>б) При ошибке выдаётся (-1).

>А остальные отрицательные значения int как-то выпали из стандарта...

но это-ж не повод для грусти... :)

а если серьёзно, может здесь и не критично, но, например, функция lseek теоретически, в некоторых случаях, может возвращать отрицательные значения, так вот там лучше всего сравнивать строго с -1... т.е. не во всех случаях это может быть валидно и лучше не привыкать к синтаксисам отличным от рекомендуемых, хотя на первый взгляд всё может быть прозрачно... обычно такие мелочия являются источниками "мистических косяков" в программе, скажем, при переносе её на другую платформу, или, к примеру, при расширении функционала другим программистом...

я рассуждаю так: если в стандарте написано, что при ошибке возвращается -1, то и ловить надо именно его, причём не забыть перед операцией обнулить переменную errno (errno = ENOENT;), а после проверить код ошибки... а то вдруг :)

вообще ИМХО в программировании лучше придерживаться стандартов настолько насколько это возможно...

shty ★★★★★
()

Написано -1, значит можешь надеяться что всегда будет -1. Второй вариант проверки чисто с эстетической точки зрения приятнее, имхо.

smh ★★★
()
Ответ на: комментарий от shty

> я рассуждаю так: если в стандарте написано, что при ошибке возвращается -1, то и ловить надо именно его, причём не забыть перед операцией обнулить переменную errno (errno = ENOENT;), а после проверить код ошибки... а то вдруг :)

ну вот как раз обнулять каждый раз errno - это прямо скажем без необходимости. если ф-я вернула ошибку - она сама выставит errno [если должна] или же это конкретный косяк ф-и. если ошибки нет - нефик трогать errno т.к. в общем случае там может быть всё, что угодно.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

>ну вот как раз обнулять каждый раз errno - это прямо скажем без необходимости. если ф-я вернула ошибку - она сама выставит errno [если должна] или же это конкретный косяк ф-и. если ошибки нет - нефик трогать errno т.к. в общем случае там может быть всё, что угодно.

ммм... ну, представим ситуацию: функция вернула отрицательное значение (но ошибки не произошло), лезем в errno, а там старый мусор.... как разруливать будем?

shty ★★★★★
()
Ответ на: комментарий от shty

> ммм... ну, представим ситуацию: функция вернула отрицательное значение (но ошибки не произошло), лезем в errno, а там старый мусор.... как разруливать будем?

если в описании функции сказано, что возврат отрицательного значения сигнализирует об ошибке - смело лезем в errno. и если там вдруг оказывается мусор, то пишем гневный багрепорт. если же отрицательное значение допустимо и не означает ошибку, то зачем лезть в errno?

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

> если в описании функции сказано, что возврат отрицательного значения сигнализирует об ошибке

ps: и, естественно, указано, что "..описание ошибки возвращается в errno..". что не всегда так (see gethostbyname(3)).

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

>если в описании функции сказано, что возврат отрицательного значения сигнализирует об ошибке - смело лезем в errno. и если там вдруг оказывается мусор, то пишем гневный багрепорт.

ну, во-первых отрицательное значение не всегда означает ошибку, а во-вторых errno вообще-то хранит код последней (!) ошибки и если у Вас уже в программе была оная то пока не пройзойдёт следующей ошибки там будет хранится именно код предыдущей, который я и обозвал мусором... так доступно?

>если же отрицательное значение допустимо и не означает ошибку, то зачем лезть в errno?

если отрицаетльное значение не обозначает ошибку - действительно незачем... однако порой возникают ситуации, когда действовать с учётом проверки errno, или не согласны?

shty ★★★★★
()
Ответ на: комментарий от shty

> ну, во-первых отрицательное значение не всегда означает ошибку, а во-вторых errno вообще-то хранит код последней (!) ошибки и если у Вас уже в программе была оная то пока не пройзойдёт следующей ошибки там будет хранится именно код предыдущей, который я и обозвал мусором... так доступно?

функция вернула ошибку - лезем в errno.
функция не вернула ошибку - не трогаем errno.

каким конкретно образом ф-я сигнализирует об ошибке - это уже зависит от конкретной ф-и и это уже не суть важно.

> если отрицаетльное значение не обозначает ошибку - действительно незачем... однако порой возникают ситуации, когда действовать с учётом проверки errno, или не согласны?

можно пример такой ситуации?

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

>функция вернула ошибку - лезем в errno. >функция не вернула ошибку - не трогаем errno.

а если это getc или fgetc которые возвращают EOF (обычно опр. как -1) при возникновении либо ошибки, либо когда достигнут конец файла, тогда что делать будете?

>>если отрицаетльное значение не обозначает ошибку - действительно незачем... однако порой возникают ситуации, когда действовать с учётом проверки errno, или не согласны?

>можно пример такой ситуации?

легко, поковыряйте маны насчёт функции:

int fwide(FILE *filep, int mode)

shty ★★★★★
()
Ответ на: комментарий от shty

> а если это getc или fgetc которые возвращают EOF (обычно опр. как -1) при возникновении либо ошибки, либо когда достигнут конец файла, тогда что делать будете?

читать документацию? там всё приписано достаточно однозначно:

http://www.opengroup.org/onlinepubs/009695399/functions/fgetc.html

--- cut ---
Upon successful completion, fgetc() shall return the next byte from the input stream pointed to by stream. If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream shall be set and fgetc() shall return EOF. If a read error occurs, the error indicator for the stream shall be set, fgetc() shall return EOF, [CX] [Option Start] and shall set errno to indicate the error. [Option End]
--- cut ---

не вижу ни одной причины вручную обнулять errno перед вызовом [f]getc(3).

> легко, поковыряйте маны насчёт функции:
> int fwide(FILE *filep, int mode)

какой, однако, экзотический пример. но тем не менее, есть такое:

http://www.opengroup.org/onlinepubs/009695399/functions/fwide.html

--- cut ---
[CX] [Option Start] Since no return value is reserved to indicate an error, an application wishing to check for error situations should set errno to 0, then call fwide(), then check errno, and if it is non-zero, assume an error has occurred. [Option End]
--- cut ---

те требование к явному обнулению errno перед вызовом - часть спецификации ф-и. что, согласитесь, совершенно не так для остальных 99.9% системных и библиотечных вызовов.

ps: белые люди обычно чуть-чуть утруждают себя и сами предоставляют документальное подтверждение своих утверждений. нет, мне не сложно найти опровержение или подтверждение тому или иному факту и я не делаю упор на чистоту спора, я уже привык. но остальным читателям темы все-таки было бы гораздо удобнее просматривать уже чистый и готовый к анализу ответ, нежели бежать и что-то где-то искать. давайте все вместе не будем лениться и постараемся приводить всю информацию. просто из уважения к читателям.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

>не вижу ни одной причины вручную обнулять errno перед вызовом [f]getc(3).

Хорошо, давайте так...

Смотрим что в манах:

"If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream shall be set and fgetc() shall return EOF. "

Здесь описано нормальное завершение по EOF. Сказано - возвращается EOF. И всё, без errno.

"If a read error occurs, the error indicator for the stream shall be set, fgetc() shall return EOF, [CX] [Option Start] and shall set errno to indicate the error."

Здесь описано завершение по ошибке. Возвращается EOF, записывается код ошибки в errno.

Теперь ситуация: предположим, что в errno лежит некий "мусор", оставшийся в наследство от исполнения предыдущей части программы (ok? бывает же), начинаем читать байты при помощи [f]getc... на итерации N получаем EOF... теперь вопрос знатокам: как понять ошибка у нас случилась или действительно EOF пришёл?

ЗЫ если что я не пальцы ставлю, мне действительно интересно как на самом деле всё происходит, ибо до сих пор я считал что в таких случаях надо занулять

>те требование к явному обнулению errno перед вызовом - часть спецификации ф-и. что, согласитесь, совершенно не так для остальных 99.9% системных и библиотечных вызовов.

Согласен, на все 100%. :)

Позволю себе напомнить к чему был пример.

---quote---

>>>однако порой возникают ситуации, когда действовать с учётом проверки errno, или не согласны?

>>можно пример такой ситуации?

>легко, поковыряйте маны насчёт функции: int fwide(FILE *filep, int mode)

---

shty ★★★★★
()
Ответ на: комментарий от klalafuda

>белые люди обычно чуть-чуть утруждают себя и сами предоставляют документальное подтверждение своих утверждений. нет, мне не сложно найти опровержение или подтверждение тому или иному факту и я не делаю упор на чистоту спора, я уже привык. но остальным читателям темы все-таки было бы гораздо удобнее просматривать уже чистый и готовый к анализу ответ, нежели бежать и что-то где-то искать. давайте все вместе не будем лениться и постараемся приводить всю информацию. просто из уважения к читателям.

ок, учту... :)

shty ★★★★★
()
Ответ на: комментарий от shty

> Теперь ситуация: предположим, что в errno лежит некий "мусор", оставшийся в наследство от исполнения предыдущей части программы (ok? бывает же),

конечно бывает

> начинаем читать байты при помощи [f]getc... на итерации N получаем EOF...

> теперь вопрос знатокам: как понять ошибка у нас случилась или действительно EOF пришёл?

ровно так, как написано в документации - проверить флаг наличия ошибки а потоке:

--- cut ---
If a read error occurs,
- the error indicator for the stream shall be set,
- fgetc() shall return EOF,
- [CX] [Option Start] and shall set errno to indicate the error.
--- cut ---

делается это через ferror(3):

http://www.opengroup.org/onlinepubs/009695399/functions/ferror.html

--- cut ---
NAME

ferror - test error indicator on a stream

SYNOPSIS

#include <stdio.h>

int ferror(FILE *stream);

DESCRIPTION

[CX] [Option Start] The functionality described on this reference page is aligned with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional. This volume of IEEE Std 1003.1-2001 defers to the ISO C standard. [Option End]

The ferror() function shall test the error indicator for the stream pointed to by stream.

RETURN VALUE

The ferror() function shall return non-zero if and only if the error indicator is set for stream.

ERRORS

No errors are defined.
--- cut ---

в результате имеем что-то на вроде этого:

FILE *fp = fopen(...);
int ch;
while ((ch = fgetc(fp)) != EOF) {
....
}
if (ferror(fp)) {
printf("Error: fgetch failed - %s\n", strerror(errno));
}

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от shty

> Здесь описано завершение по ошибке. Возвращается EOF, записывается код ошибки в errno.

btw если после получения EOF из getch() сразу проверять значение errno игнорируя ferror(), то можно получить как раз противоположный эффект: в errno при успешном завершении getch() может в принципе находиться всё, что угодно, и есть риск обнаружить "ошибку" в случае, когда в действительности её не было. причём даже если вручную обнулить errno перед вызовом getch() - это ещё не даёт гарантии того, что по выходу из getch() ненулевое значение errno обязательно сигнализирует об ошибке. к примеру, getch() может внутри вызывать read() несколько раз и один из которых завершился с ошибкой и испортил значение errno, но в конечном итоге ошибки нет. да мало ли что может быть.

// wbr

klalafuda ★☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.