Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Есть ли аналог exception?


Автор: Anton Vatchenko 11.4.2007, 17:08
Пишу сервер... В нем во многих местах идет чтение из сокета. И тут я узнаю, что соединение закрыто, то есть нужно выйти из цикла... Но проблема в том, что это узнает моя функция read, а она может быть вызвана из другой функции и т. д... Не делать же типа того:

while(1) {
    int i = read(socket);
    if(i == -1) break;
    int j = read(socket);
    if(j == -1) break;
    int lost = 0;
    for(int k = 0; k < 20; k++) {
        a[k] = read(socket);
        if(a[k] == -1) { lost = 1; break;}
    }
    if(lost) break;
}

Автор: boombick 11.4.2007, 17:10
А что это за язык? и почему в общих вопросах по никсам?

Автор: powerfox 11.4.2007, 17:12
Модератор: тема перенесена в общие вопросы по С/С++

Посмотри в стандартной библиотеке Си break и setjmp.h

Автор: Anton Vatchenko 11.4.2007, 17:20
Блин, я именно про Линуксы спрашивал...

Автор: Daevaorn 11.4.2007, 17:24
Цитата(Anton Vatchenko @  11.4.2007,  18:20 Найти цитируемый пост)
Блин, я именно про Линуксы спрашивал...

а это не имеет значения. решение тебе уже посказали

Автор: powerfox 11.4.2007, 17:33
Цитата(Anton Vatchenko @  11.4.2007,  18:20 Найти цитируемый пост)
Блин, я именно про Линуксы спрашивал... 

Вопрос к линуксу не имеет отношения. Это вопрос по ЯП. 

Автор: likehood 11.4.2007, 17:35
goto

Автор: Anton Vatchenko 11.4.2007, 17:43
А эти джампы не такие медленные как goto? А break не понял в каком контексте использовать? Он вроде не выйдет из вложенных функций...

Автор: Mayk 11.4.2007, 17:44
Цитата(likehood @  11.4.2007,  21:35 Найти цитируемый пост)
goto 

Не худший вариант в случае одной функции.
Цитата(Anton Vatchenko @  11.4.2007,  21:08 Найти цитируемый пост)
моя функция read, а она может быть вызвана из другой функции и т. д... Не делать же типа того:

для многих не очень хорошо работает.

Цитата(powerfox @  11.4.2007,  21:12 Найти цитируемый пост)
setjmp


Автор: powerfox 11.4.2007, 17:54
Цитата(Anton Vatchenko @  11.4.2007,  18:43 Найти цитируемый пост)
А эти джампы не такие медленные как goto?

Гм... А где тут медлительность может быть? По идее, просто начинает выполняться другая функция (в 2-х словах, если).

Автор: MAKCim 11.4.2007, 18:36
Цитата(Anton Vatchenko @  11.4.2007,  17:43 Найти цитируемый пост)
А эти джампы не такие медленные как goto?

goto вообще быстрее (или по крайней мере не медленнее) вызова функции
(goto = jmp, вызов функции = call)

Автор: ivashkanet 11.4.2007, 18:41
Товарищи, а почему бы просто не вызвать
Код

return #errorCode; // вроде так зарезервированные в define  константы обозначаются (могу сиииильно ошибаться) :)
// Например
return null 

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

Механизм exception-ов вшит в сам язык, так что он может разворачивать стек (что он и делает), а вот программно так не сделать 

P.S. Все мое личное, ИМХО

Автор: MAKCim 11.4.2007, 18:52
ivashkanet
пример
Код

int do_code() {
    key_t key = ftok(KEY_PATH, 0);
    if (key < 0) 
        return errno; /* тут все нормально */
    int sem_id = semget(key, SEMAPHORES_COUNT, IPC_CREAT | IPC_EXCL | 0666);
    if (sem_id < 0) 
        return errno; /* тут тоже все хорошо */
    int shm_id = shmget(key, PAGE_SIZE, IPC_CREAT | IPC_EXCL | 0222);
    if (shm_id < 0) /* а вот тут уже не хорошо, потому как семафор уже создан и необходимо его освободить */
        goto destroy_sem;
    int fd = open(PATH, O_RDONLY);
    if (fd < 0) /* а тут совсем нехорошо, надо освободить и семафор, и shared memory */
        goto destroy_shm;
    void *ptr = malloc(PAGE_SIZE);
    if (ptr == NULL) /* а тут катастрофа - 3 открытых ресурса */
        goto destroy_file;
...
destroy_file:
    close(fd);
destroy_shm:
    shmctl(shm_id, IPC_RMID, NULL);
destroy_sem:
    semctl(sem_id, 0, IPC_RMID);
}

это я к чему, goto позволяет логично и наглядно решить проблему, которая описана выше
и пусть противники goto найдут более понятное решение  smile 

Автор: powerfox 11.4.2007, 18:54
Цитата(ivashkanet @  11.4.2007,  19:41 Найти цитируемый пост)
Механизм exception-ов вшит в сам язык, так что он может разворачивать стек (что он и делает), а вот программно так не сделать 

Я не уверен в этом. Можно реализовать какую-нибудь функции exception(bla-bla);
А там обрабатывать bla-bla и иметь набо goto.
Хотя я exception практически не юзал.

Автор: bilbobagginz 11.4.2007, 19:10
Цитата(powerfox)

Можно реализовать какую-нибудь функции exception(bla-bla);

powerfox, можно вручную реализовать и классы, и наследование... только на фига оно надо, если есть C++ smile

кроме того, есть переходный момент между C и C++, называется objective C.
может быть это то, что нужно человеку...но я правда не понимаю зачем писать что-то на Си, если можно использовать готовые средства Си++.



Автор: Rockie 11.4.2007, 19:23
Цитата(Anton Vatchenko @  11.4.2007,  17:08 Найти цитируемый пост)
Пишу сервер... В нем во многих местах идет чтение из сокета. И тут я узнаю, что соединение закрыто, то есть нужно выйти из цикла... Но проблема в том, что это узнает моя функция read, а она может быть вызвана из другой функции и т. д...

Anton Vatchenko, вопрос не оч. понятен, но наверное можно использовать глобальную переменную - флаг, например:
Код
int isSocketClosed = 0;

и уже из разных функций считывать/устанавливать ее значение.


Автор: MAKCim 11.4.2007, 19:24
Цитата(bilbobagginz @  11.4.2007,  19:10 Найти цитируемый пост)
но я правда не понимаю зачем писать что-то на Си, если можно использовать готовые средства Си++.

хм, интересная логика

Автор: bilbobagginz 11.4.2007, 19:48
MAKCim, я сам на Си пишу, когда нужно smile
я не против Си, а к тому, что если уже пишешь приложение на Си, нужно серьезно взвешивать, если это и есть путь истинный - коли тебе нужны исключения и т.д. - не фиг писАть на Си.

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

Автор: ivashkanet 11.4.2007, 20:44
Цитата(MAKCim @  11.4.2007,  17:52 Найти цитируемый пост)
ivashkanet, пример

MAKCim, хороший пример, но: у тебя только одна функция, а не 
Цитата(Anton Vatchenko @  11.4.2007,  16:08 Найти цитируемый пост)
она может быть вызвана из другой функции и т. д...

В пределах одной функции проблема ясна и решается более-менее просто.

Вопрос ведь в том, как "просигналить" функциям которые выше текущей по стеку, а не в том, как обработать ситуацию в самой функции.
Цитата(powerfox @  11.4.2007,  17:54 Найти цитируемый пост)
Можно реализовать какую-нибудь функции exception(bla-bla);
А там обрабатывать bla-bla и иметь набо goto.

Не совсем понятно, но все же:
В С/С++ можно "прыгать" за пределы функции в другую функцию? И что тогда будет со стеком, что будет с методом, который вызвал эту функцию и ожидает ответа от нее?

В любом случае механизм получится негибким. Что будет если мы захотим добавть новую функцию в цепочку...
Цитата(Rockie @  11.4.2007,  18:23 Найти цитируемый пост)
int isSocketClosed = 0;

ИМХО, лучший способ. А вместо try/catch --- if/else
Правда наличие выставленного флага не прерывает выполнение функции и не ищет "ближайшую инструкцию отлова этого флага" (как в случае с exception), но это, все-таки, решение.

Автор: MAKCim 11.4.2007, 21:37
Цитата(ivashkanet @  11.4.2007,  20:44 Найти цитируемый пост)
Вопрос ведь в том, как "просигналить" функциям которые выше текущей по стеку, а не в том, как обработать ситуацию в самой функции.

ошибки в функциях обрабатывать с помоощью goto <обработчик> и возвращать код ошибки
применяя рекурсивно данный подход ко всем функциям в программе - решаем проблему
Код

int do_code() {
    int error = 0; /* ошибки нет */
    key_t key = ftok(KEY_PATH, 0);
    if (key < 0) 
        return errno; /* тут все нормально */
    int sem_id = semget(key, SEMAPHORES_COUNT, IPC_CREAT | IPC_EXCL | 0666);
    if (sem_id < 0)
        return errno; /* тут тоже все хорошо */
    int shm_id = shmget(key, PAGE_SIZE, IPC_CREAT | IPC_EXCL | 0222);
    if (shm_id < 0) { /* а вот тут уже не хорошо, потому как семафор уже создан и необходимо его освободить */
        error = errno;
        goto destroy_sem;
    }
    int fd = open(PATH, O_RDONLY);
    if (fd < 0) { /* а тут совсем нехорошо, надо освободить и семафор, и shared memory */
        error = errno;
        goto destroy_shm;
    }
    void *ptr = malloc(PAGE_SIZE);
    if (ptr == NULL) /* а тут катастрофа - 3 открытых ресурса */
        goto destroy_file;
...
destroy_file:
    close(fd);
destroy_shm:
    shmctl(shm_id, IPC_RMID, NULL);
destroy_sem:
    semctl(sem_id, 0, IPC_RMID);
success:
    return error; /* 0 или код ошибки */
}


Добавлено через 2 минуты и 28 секунд
bilbobagginz
вообщем согласен
но, имхо, исключения - это не такая большая проблема, чтобы менять язык разработки

Автор: ivashkanet 12.4.2007, 08:44
Цитата(MAKCim @  11.4.2007,  20:37 Найти цитируемый пост)
ошибки в функциях обрабатывать с помоощью goto <обработчик>

Повторяю еще раз: внутри самой функции можно хоть с ГоуТами, хоть с Ифами, хоть с чем угодно.
Твой код, например, можно запросто переписать не используя goto и смотреться он будет не менее красиво.
Цитата(MAKCim @  11.4.2007,  20:37 Найти цитируемый пост)
возвращать код ошибки
применяя рекурсивно данный подход ко всем функциям в программе - решаем проблему

Вот тут самая тонкость. Но все же, это решение (которое я давал несколькими постами выше).

Итог (личное мое ИМХО):
Лучший вариант --- возвращать код ошибки и обрабатывать его во всех функциях, которые в этом нуждаются.
Тоже вариант --- выставлять некий флаг и "ждать" его в определенном месте, если он пришел, то объявлять ошибочными все данные полученные до этой строчки и обрабатывать ошибку. (этот вариант ближе к механизму exception'ов, но, ИМХО, хуже, так как выполнение программы продолжается).

Автор: MAKCim 12.4.2007, 08:51
Цитата(ivashkanet @  12.4.2007,  08:44 Найти цитируемый пост)
Твой код, например, можно запросто переписать не используя goto и смотреться он будет не менее красиво.

 smile  smile  smile 
(только на С пожалуйста)

Автор: bilbobagginz 12.4.2007, 10:07
Цитата

но, имхо, исключения - это не такая большая проблема, чтобы менять язык разработки 

смотря какие аспекты механизма исключения тебе нужны.

да, хотелось бы видеть читабельный и удобный для доработок примерчик без goto smile

(сумлеваюсь, что есть такой...)

Автор: ivashkanet 12.4.2007, 12:35
MAKCimbilbobagginz, вот пример без goto и, ИМХО, не менее читабельный (по мне, даже более)
+ работа с ресурсами и "сборка мусора" превратились в два, относительно, независимых процесса.

1) Вариант кода с излишними коментариями:
Код

        int do_code()
        {
            int errno = -1269; // Код ошибки

            int error = 0; /* ошибки нет */
            int key = ftok(KEY_PATH, 0);
            if (key < 0)
                return errno; /* тут все нормально */
            int sem_id = semget(key, SEMAPHORES_COUNT, IPC_CREAT | IPC_EXCL | 0666);
            if (sem_id < 0)
                return errno; /* тут тоже все хорошо */
            // Так как выше все нормально, то я это не трогал, 
            // но все же я бы это тоже поменял

            // Начало моего кода
            // Единственное, пришлось объявлять переменные отдельно
            int fd;
            void *ptr;

            int shm_id = shmget(key, PAGE_SIZE, IPC_CREAT | IPC_EXCL | 0222);
            if (shm_id >= 0)
            {
                fd = open(PATH, O_RDONLY);
                if (fd >= 0)
                {
                    ptr = malloc(PAGE_SIZE);
                    if (ptr != NULL)
                    {
                        //
                        // работаем с полученными ресурсами
                        //
                    }
                    /* а тут катастрофа - 3 открытых ресурса */
                    //ничего не делаем. "Сборка мусора" и установка флага ошибки будет в конце функции
                }
                /* а тут совсем нехорошо, надо освободить и семафор, и shared memory */
                //ничего не делаем. "Сборка мусора" и установка флага ошибки будет в конце функции
            }
            /* а вот тут уже не хорошо, потому как семафор уже создан и необходимо его освободить */
            //ничего не делаем. "Сборка мусора" и установка флага ошибки будет в конце функции


            if (sem_id >= 0)
            {
                semctl(sem_id);
                if (shm_id >= 0)
                {
                    shmctl(shm_id);
                    if (fd >= 0) 
                    { 
                        close(fd);
                        if (ptr == null) { /* все 3 ресурса созданы, а ptr -- нулл => ошибка */ error = errno; }
                    }
                    else { /* семафор и shared memory созданы, а дескриптор нет => ошибка */ error = errno; }
                }
                else { /* семафор создан, а shared memory нет => ошибка */ error = errno; }
            }

            return error;
        }


2) Вариант того же кода, но без лишних коментариев:
Код

        int do_code()
        {
            int errno = -1269; // Код ошибки

            int error = 0; /* ошибки нет */
            int key = ftok(KEY_PATH, 0);
            if (key < 0)
                return errno; /* тут все нормально */

            int sem_id = semget(key, SEMAPHORES_COUNT, IPC_CREAT | IPC_EXCL | 0666);
            if (sem_id < 0)
                return errno; /* тут тоже все хорошо */


            // Начало моего кода
            int fd;
            object ptr;

            int shm_id = shmget(key, PAGE_SIZE, IPC_CREAT | IPC_EXCL | 0222);
            if (shm_id >= 0)
            {
                fd = open();
                if (fd >= 0)
                {
                    ptr = malloc();
                    if (ptr != null)
                    {
                        // работаем с полученными ресурсами
                    }
                }
            }

            // "Сборка мусора и отлов ошибок"
            if (sem_id >= 0)
            {
                semctl(sem_id);
                if (shm_id >= 0)
                {
                    shmctl(shm_id);
                    if (fd >= 0) 
                    { 
                        close(fd);
                        if (ptr == null) { /* все 3 ресурса созданы, а ptr -- нулл => ошибка */ error = errno; }
                    }
                    else { /* семафор и shared memory созданы, а дескриптор нет => ошибка */ error = errno; }
                }
                else { /* семафор создан, а shared memory нет => ошибка */ error = errno; }
            }

            return error;
        }


Жду ваших комментариев  smile 

P.S. Код отформатирован так, как я люблю, поэтому он кажется громоздким. Но если его отформатировать в стиле MAKCim'а, то он будет не намного больше, чем с goto.
P.P.S. "Отлов ошибок" можно было оставить и в первом блоке, но, ИМХО, ему логичнее быть именно во втором.
P.P.P.S. Проверил несколько раз, но все равно могут быть несостыковки, так что сильно ногами не пинать smile

Добавлено через 13 минут и 43 секунды
А если еще совместить первые два блока, то еще лучше получится:
Код

        int do_code()
        {
            int errno = -1269; // Код ошибки

            int error = 0; /* ошибки нет */
            int key = ftok(KEY_PATH, 0);
            if (key < 0)
                return errno; /* тут все нормально */
            int sem_id = semget(key, SEMAPHORES_COUNT, IPC_CREAT | IPC_EXCL | 0666);
            if (sem_id < 0)
                return errno; /* тут тоже все хорошо */

            // Начало моего кода
            int fd;
            object ptr;

            int shm_id = shmget(key, PAGE_SIZE, IPC_CREAT | IPC_EXCL | 0222);
            if (shm_id >= 0){
                fd = open();
                if (fd >= 0){
                    ptr = malloc();
                    if (ptr != NULL){
                        // работаем с полученными ресурсами
                    }
                    else { /* все 3 ресурса созданы, а ptr -- нулл => ошибка */ error = errno; }
                    close(fd); // уничтожаем дескриптор, так как он уже не нужен
                }
                else { /* семафор и shared memory созданы, а дескриптор нет => ошибка */ error = errno; }
                shmctl(shm_id); // уничтожаем shared memory, за ненадобностью
            }
            else { /* семафор создан, а shared memory нет => ошибка */ error = errno; }
            semctl(sem_id); // уничтожаем семафор, за ненадобностью

            return error;
        }

Автор: powerfox 12.4.2007, 15:13
ivashkanet, твой код ничем особенным не отличается от кода Максима, так как ты, по сути дела, просто перенёс тела функций по обработке ошибок в основную, что не есть хорошо:
1. Такой стиль подвержен ошибкам + тяжело их отслеживать (делать локализацию ошибки).
2. Если ошибка возникла в самом начале, то зачем продолжать выполнение функции? Это лишнее время (пользователя и машинное).
3. Читается хуже. Читающий программу увидит, конечно, что ты в случае ошибки что-то творишь с переменной error (и прочее), но чем рысскать по коду, лучше сразу перейти к функциям-обработчикам.

Код Максима - классический пример того, как подобные вещи пишутся на Си.

Автор: ivashkanet 12.4.2007, 16:29
Цитата(powerfox @  12.4.2007,  14:13 Найти цитируемый пост)
ничем особенным не отличается от кода Максима

Даже больше: ничем, кроме отсутствия goto
Цитата(powerfox @  12.4.2007,  14:13 Найти цитируемый пост)
1. Такой стиль подвержен ошибкам + тяжело их отслеживать (делать локализацию ошибки).

Кто к чему привык ;-) Мне понятнее мой вариант. Тем более с нормальными коментариями.
Цитата(powerfox @  12.4.2007,  14:13 Найти цитируемый пост)
2. Если ошибка возникла в самом начале, то зачем продолжать выполнение функции? Это лишнее время (пользователя и машинное).

Посмотри внимательно, ИМХО, у меня нет ни одной лишней инструкции после возникновения ошибки. Только то, что нужно для удаления ресурсов.
Цитата(powerfox @  12.4.2007,  14:13 Найти цитируемый пост)
3. Читается хуже. Читающий программу увидит, конечно, что ты в случае ошибки что-то творишь с переменной error (и прочее), но чем рысскать по коду, лучше сразу перейти к функциям-обработчикам.

То же что и по первому пункту.
Цитата(powerfox @  12.4.2007,  14:13 Найти цитируемый пост)
Код Максима - классический пример того, как подобные вещи пишутся на Си. 

Разные задачи требуют разные подходы к ее решению. В данном случае, когда требуется скорость работы, код Максима, возможно, и лучше.

Добавлено через 1 минуту и 6 секунд
Цитата(powerfox @  12.4.2007,  14:13 Найти цитируемый пост)
ты, по сути дела, просто перенёс тела функций по обработке ошибок в основную

Вот это я не понял :(

Автор: powerfox 12.4.2007, 17:10
Цитата(ivashkanet @  12.4.2007,  17:29 Найти цитируемый пост)
осмотри внимательно, ИМХО, у меня нет ни одной лишней инструкции после возникновения ошибки. Только то, что нужно для удаления ресурсов.


Извини, просто невчитался.
Цитата(ivashkanet @  12.4.2007,  17:29 Найти цитируемый пост)
Цитата(powerfox @  12.4.2007,  14:13 Найти цитируемый пост)
ты, по сути дела, просто перенёс тела функций по обработке ошибок в основную

Вот это я не понял :( 


По поводу стиля, я мнение не поменял. Но по поводу конкретного примера: Максим для каждой ошибки вызывал свой разработчик. Ты возвращаешь код ошибки, то есть функция, которая получила его, должна сама что-то предпринять.

Автор: MAKCim 12.4.2007, 17:15
ivashkanet
не все так гладко  smile 
по функционалу, конечно, все верно, но
1. Код менее читабелен (имхо)
2. Количество вложенных if-ов растет пропорционально количеству выделенных ресурсов
3. Необходимость повторения "лесенки" из if-ов 2 раза
4. Эффективность кода страдает (вложенные if-ы при всей оптимизации ничего хорошего кроме частой перезагрузки конвеера не дают)
Цитата(ivashkanet @  12.4.2007,  16:29 Найти цитируемый пост)
Разные задачи требуют разные подходы к ее решению. В данном случае, когда требуется скорость работы, код Максима, возможно, и лучше.

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

Автор: ivashkanet 12.4.2007, 17:20
Цитата(powerfox @  12.4.2007,  16:10 Найти цитируемый пост)
Максим для каждой ошибки вызывал свой разработчик. Ты возвращаешь код ошибки, то есть функция, которая получила его, должна сама что-то предпринять. 

goto: xy --- это вызов своего обработчика? Не согласен.

Мой код делает ТО ЖЕ САМОЕ, что и код Максима.

P.S. ИМХО, если взять ну очень умный компилятор, то он должен преобразовать мой и Максима код в одни и те же инструкции. Причем, эти инструкции будут ближе к коду Максима (это только потому, что компиляторы вовсю используют goto направо и налево smile ).

Добавлено через 10 минут и 57 секунд
MAKCim,  smile 

Цитата(MAKCim @  12.4.2007,  16:15 Найти цитируемый пост)
3. Необходимость повторения "лесенки" из if-ов 2 раза

Вторую "лесенку" можно заменить на отдельные if-ы, правда код будет менее эффективен.
Цитата(MAKCim @  12.4.2007,  16:15 Найти цитируемый пост)
2. Количество вложенных if-ов растет пропорционально количеству выделенных ресурсов

Наличию связанных выделенных ресурсов.
Цитата(MAKCim @  12.4.2007,  16:15 Найти цитируемый пост)
я не знаю, ты конечно можешь утверждать, что тебе он понятнее и т. п, но, честно говоря, если бы такой код, как у тебя, попался мне в реальном проекте, я бы его скорее всего (если бы была такая возможность) переписал 

А никто не говорит, что я такой код написал бы у себя в проекте, боже упаси  smile
Просто я предоставил код без goto максимально приближенный к твоему.

Автор: MAKCim 12.4.2007, 17:37
Цитата(ivashkanet @  12.4.2007,  17:20 Найти цитируемый пост)
это только потому, что компиляторы вовсю используют goto направо и налево smile 

goto = jmp, вызов функции = call, jmp - более эффективен
Цитата(ivashkanet @  12.4.2007,  17:20 Найти цитируемый пост)
Наличию связанных выделенных ресурсов.

без разницы, связаны они или нет, главное их освободить
кроме того, в моем примере только создание ключа (ftok()) связано с возможностью дальнейшего выполнения

Автор: ivashkanet 12.4.2007, 17:41
Короче, не буду я с вами спорить smile
Опыта работы с ресурсами, которые нужно освобождать, у меня нет, поэтому я не владею нужными навыками. 
Возможно, я бы использовал goto в этом случае, а может использовал бы другой алгоритм -- не знаю.

P.S. Ну и наофтопили мы тут  smile 

Автор: MAKCim 12.4.2007, 17:46
Цитата(ivashkanet @  12.4.2007,  17:41 Найти цитируемый пост)
P.S. Ну и наофтопили мы тут

как раз все по теме  smile 

Автор: powerfox 12.4.2007, 17:49
Цитата(ivashkanet @  12.4.2007,  18:20 Найти цитируемый пост)
goto: xy --- это вызов своего обработчика? Не согласен.

Мой код делает ТО ЖЕ САМОЕ, что и код Максима.


Цитата(MAKCim @  11.4.2007,  22:37 Найти цитируемый пост)
goto destroy_sem;


Цитата(MAKCim @  11.4.2007,  22:37 Найти цитируемый пост)
goto destroy_shm;


Цитата(MAKCim @  11.4.2007,  22:37 Найти цитируемый пост)
goto destroy_file;


Не то же самое. У тебя идёт возврат в вызывающую функцию, которая обрабатывает errcode, а у Максима в обработчик ошибок.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)