Вы можете описать ситуацию, когда неправильный порядок *разблокировки*, т.е. отпускания мьютексов, приводит к проблемам? Ситуации, когда { unlock(A); unlock(B); } корректно, а { unlock(B); unlock(A); } ведет к deadlock-y?
> и, наконец, разблокируем все мьютексы в обратном порядке — справа налево. Не забываем, что основная причина deadlock – несоблюдение порядка блокировки/разблокировки нескольких мьютексов.
Разве порядок разблокировки может быть причиной deadlock? «Неправильная» разблокировка (слева направо, в данном случае) может привести к образованию конвоя или thundering herd, но никак не к deadlock-у.
> Вы, похоже, пытаетесь выкрутиться из ситуации, придираясь к слову «разыменование».
В моих комментариях, которые вам необходимо перечитать, с самого начала и неоднократно было указано, что я понимаю «разыменование», как применение unary operator *. Каким образом вы его понимаете — до сих пор непонятно.
> Но это не так важно, ибо соответствующий раздел — «informative», а не «normative».
Есть другие примеры undefined behaviour, которые авторы решили не включать в этот список, или это удивительное исключение?
> Речь в данном разговоре идет о формальной легальности конструкции (size_t)&(((s *)0)-›m)
Очень жаль, что вы все время об этом разговаривали, потому что я, как как и было написано в моем первом сообщении, говорю о том, что в этой конструкции нет разыменования (т.е. применения unary *), вне зависимости от того, легальна ли вся конструкция.
Например (приходится повторить), в конструкции A[B] есть разыменование, потому что стандарт явно определяет ее как (*(A+B)). Для конструкции A->B такого сведения нет. Вы, кажется, пользуетесь каким-то своим неформальным пониманием разыменования, не определив его явно.
> И этк конструкция — нелегальна, ибо содержит применение оператора -> к указателю, не являющемуся указателем на объект.
Вы можете процитировать соответствующий пункт из списка undefined behaviours в конце стандарта?
> Наоборот 6.5.3.2/1 это запрещает.
Где конкретно? Там явно написано «The operand of the unary & operator shall be [...] unary * operator» и никаких ограничений на аргумент * нет, т.е. явно разрешается &(*(X)) для произвольного X.
Что значит «предотвращает запрещенное разыменование»? Стандарт просто отмечает, примечанием, что результат &(*0) должен быть 0, там ничего не говорится ни про какую «аннигиляцию».
> Оператор -> — это разыменование указателя.
Смешались в кучу кони, люди. :-)
С точки зрения стандарта, -> это не разыменование, семантика -> описана специальным образом (6.5.2.3), но стандарт гарантирует, что при некоторых условиях (X)->Y эквивалентно (*(X)).Y (примечание 69).
С неформальной точки зрения, offsetof(A, B) это просто константа компиляции, и никакого разыменования, т.е. обращения к памяти, ее вычисление не требует.
> На такой платформе такая реализация offsetof работать не будет.
С этим никто не спорит, у offset() есть и гораздо менее экзотические проблемы. И также понятно, что традиционная реализация вызывает undefined behaviour. Но вовсе не из-за отсутствующего там разыменования, а потому, что семантика A->B стандартом не сводится к арифметике над указателями (в отличие от семантики A[B]).
Обычный offsetof() может привести к undefined behaviour, когда применяется как offsetof(struct foo, array[n]), где n — больше числа задекларированных элементов в поле-массиве. Типичная ситуация: массив нулевой длины в конце структуры, фактически память под массив выделяется при аллокации.
Во-первых, применять адресную арифметику к null pointer стандартом C явно разрешено (см. C99, 6.5.3.2, особенно примечание 74, где явно указано, что даже разыменование нулевого указателя бывает законно). Во-вторых «разыменование null pointer» это применение операции разыменования (unary * operator) к нулевому указателю, а в макросе offsetof() такая операция просто-напросто отсутствует: этот макрос ничего не разыменовывает.
> А между тем еще в Турбо Паскале была возможность вкладывать одни функции в другие.
Как уточнение: вложенные функции были в Паскале с самого начала и, вообще, присутствуют почти во всех языках, происходящих от Алгола-60, C здесь как-раз исключение.
> Однако, это является неопределенным поведением по стандарту Си (из-за разыменования нуля)
offsetof() NULL не разыменовывает, он выполняет арифметические операции над NULL-pointer, что совершенно законно.
> Этот механизм в чем-то похож на уровень привилегий х86.
Этот массив дескрипторов называется Dijkstra display: http://cs-exhibitions.uni-klu.ac.at/index.php?id=4&uid=9.
> Однако такая конфигурация обладает рядом свойств, которые сильно затрудняют работу с ней в случае, когда клиенты используют независимые виртуализированные кластера.
Вы не могли бы пояснить, какие проблемы у Люстры в такой конфигурации?
Разве порядок разблокировки может быть причиной deadlock? «Неправильная» разблокировка (слева направо, в данном случае) может привести к образованию конвоя или thundering herd, но никак не к deadlock-у.
В моих комментариях, которые вам необходимо перечитать, с самого начала и неоднократно было указано, что я понимаю «разыменование», как применение unary operator *. Каким образом вы его понимаете — до сих пор непонятно.
> Но это не так важно, ибо соответствующий раздел — «informative», а не «normative».
Есть другие примеры undefined behaviour, которые авторы решили не включать в этот список, или это удивительное исключение?
Очень жаль, что вы все время об этом разговаривали, потому что я, как как и было написано в моем первом сообщении, говорю о том, что в этой конструкции нет разыменования (т.е. применения unary *), вне зависимости от того, легальна ли вся конструкция.
Например (приходится повторить), в конструкции A[B] есть разыменование, потому что стандарт явно определяет ее как (*(A+B)). Для конструкции A->B такого сведения нет. Вы, кажется, пользуетесь каким-то своим неформальным пониманием разыменования, не определив его явно.
> И этк конструкция — нелегальна, ибо содержит применение оператора -> к указателю, не являющемуся указателем на объект.
Вы можете процитировать соответствующий пункт из списка undefined behaviours в конце стандарта?
Где конкретно? Там явно написано «The operand of the unary & operator shall be [...] unary * operator» и никаких ограничений на аргумент * нет, т.е. явно разрешается &(*(X)) для произвольного X.
Что значит «предотвращает запрещенное разыменование»? Стандарт просто отмечает, примечанием, что результат &(*0) должен быть 0, там ничего не говорится ни про какую «аннигиляцию».
> Оператор -> — это разыменование указателя.
Смешались в кучу кони, люди. :-)
С точки зрения стандарта, -> это не разыменование, семантика -> описана специальным образом (6.5.2.3), но стандарт гарантирует, что при некоторых условиях (X)->Y эквивалентно (*(X)).Y (примечание 69).
С неформальной точки зрения, offsetof(A, B) это просто константа компиляции, и никакого разыменования, т.е. обращения к памяти, ее вычисление не требует.
> На такой платформе такая реализация offsetof работать не будет.
С этим никто не спорит, у offset() есть и гораздо менее экзотические проблемы. И также понятно, что традиционная реализация вызывает undefined behaviour. Но вовсе не из-за отсутствующего там разыменования, а потому, что семантика A->B стандартом не сводится к арифметике над указателями (в отличие от семантики A[B]).
Как уточнение: вложенные функции были в Паскале с самого начала и, вообще, присутствуют почти во всех языках, происходящих от Алгола-60, C здесь как-раз исключение.
> Однако, это является неопределенным поведением по стандарту Си (из-за разыменования нуля)
offsetof() NULL не разыменовывает, он выполняет арифметические операции над NULL-pointer, что совершенно законно.
Этот массив дескрипторов называется Dijkstra display: http://cs-exhibitions.uni-klu.ac.at/index.php?id=4&uid=9.
«Направление».
Вы не могли бы пояснить, какие проблемы у Люстры в такой конфигурации?
Кроме того, Алгол-68 (на котором приведен пример) и Алгол-60 это совершенно разные языки.