2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3, 4, 5
 
 Re: c++ задача на битовые операции
Сообщение29.11.2019, 19:41 
Заслуженный участник
Аватара пользователя


16/07/14
9149
Цюрих
Seman в сообщении #1428180 писал(а):
Чтобы что-то обосновать, надо <...>
Давайте лучше наоборот: вы возьмете ваш код, и, ссылаясь везде где нужно на стандарт, покажете, что он делает то, что вы заявляете? А то как-то нечестно: я вам стандарт цитирую, привожу примеры, когда явно видно, что UB приводит к неожиданным результатам, а вы сидите и требуете еще (причем по вашему же признанию не разобравшись в том, что вам сообщили раньше).

Вопрос не про приведение указателей - можно к char* любой указатель (и обратно, если он правильно выровнен). Вопрос про разыменование того, что получилось приведением char* к чему-то еще. Ну и вообще про то, какой тип мы читаем, и какой тип там реально лежит. Исчерпывающий список, что как что можно читать, приведен выше. В частности, чтение int32_t из места, где лежит int64_t, в этот список не входит.

 Профиль  
                  
 
 Re: c++ задача на битовые операции
Сообщение29.11.2019, 20:54 


29/12/13
306
mihaild в сообщении #1428187 писал(а):
Давайте лучше наоборот:
Не согласен, лучший валидатор это компилятор. Программа компилируется без ошибок и предупреждений даже с педантичными опциями и проверкой на UB. В gcc есть опция -pedantic. Она должна отображать все предупреждения, что несоответствует стандарту.
Цитата:
-pedantic

Issue all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C and ISO C++. For ISO C, follows the version of the ISO C standard specified by any -std option used.
https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

Кроме того, есть ещё ubsan, служит для проверки на UB, требует установки libubsan в системе. Используется с опцией -fsanitize
Цитата:
-fsanitize=undefined

Enable UndefinedBehaviorSanitizer, a fast undefined behavior detector. Various computations are instrumented to detect undefined behavior at runtime.
https://gcc.gnu.org/onlinedocs/gcc/Inst ... tions.html
https://developers.redhat.com/blog/2014 ... zer-ubsan/

Изображение

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

 Профиль  
                  
 
 Re: c++ задача на битовые операции
Сообщение29.11.2019, 21:01 
Экс-модератор
Аватара пользователя


23/12/05
12064
Seman, справедливости ради, gcc - не единственный компилятор.

 Профиль  
                  
 
 Re: c++ задача на битовые операции
Сообщение29.11.2019, 21:15 


29/12/13
306
photon в сообщении #1428203 писал(а):
Seman, справедливости ради, gcc - не единственный компилятор.
Да, я же не спорю. Но он вроде как в соответствии со стандартом сделан, и эти опции, наверное, должны были выдать какие предупреждения(даже ошибки), если действительно, что страшное в коде.
Цитата:
GCC has almost full support for the latest revision of the C++ standard,

https://gcc.gnu.org/projects/cxx-status.html#cxx17

 Профиль  
                  
 
 Re: c++ задача на битовые операции
Сообщение29.11.2019, 21:56 
Заслуженный участник
Аватара пользователя


16/07/14
9149
Цюрих
Seman в сообщении #1428201 писал(а):
Не согласен, лучший валидатор это компилятор
Это неправда.
Даже если компилятор соблюдает стандарт (что довольно редко является правдой - ни gcc, ни clang на текущий момент полностью С++17 не поддерживают), он уж точно не гарантирует, что код, написанный не по стандарту, работать не будет никак (и это в общем случае невозможно гарантировать). Равно он не гарантирует, что написанный не по стандарту код в следующей версии будет работать так же, как в текущей. И довольно часто происходит, что где-то написали код "ну сейчас же работает", потом компилятор / стандартную библиотеку обновляли, и код работать переставал. Один из известных примеров - в flash в memcpy исходная и целевая области пересекались. Пока копирование шло простым способом слева направа - всё работало.
Потом порядок поменяли - и всё работать перестало.
Seman в сообщении #1428201 писал(а):
Она должна отображать все предупреждения, что несоответствует стандарту.
Только про синтаксис.
На практике компилятор предупреждает про некоторые моменты, которые в рантайме заведомо приведут к UB. Но не про все.
Seman в сообщении #1428201 писал(а):
есть ещё ubsan
Который, безусловно, очень полезная утилита, но никаких гарантий не дает.
Seman в сообщении #1428201 писал(а):
мой код со всеми этими опциями компилируется без ошибок и предупреждений, при запуске программа выдает, что должна
А если его сделать совсем чуть-чуть интереснее, то идет разброд и шатание: один и тот же код работает по-разному в зависимости от того, вынесен ли он из main в отдельную функцию, и скомпилирован ли с санитайзером или без
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <iostream>

using namespace std;

void f(uint64_t* tt, char* tt1) {
        uint32_t tt32_1 = *(reinterpret_cast<uint32_t*>(&(tt1[0]))) ;
    *tt -= 1;
        uint32_t tt32_2 = *(reinterpret_cast<uint32_t*>(&(tt1[0]))) ;
    std::cout << tt32_1 << ' ' << tt32_2 << ' ' << (tt32_1 == tt32_2) << '\t';
}

int main()
{
        uint64_t tt = 1;
        char* tt1 = reinterpret_cast<char*>(&tt);
    f(&tt, tt1);
    tt = 1;

        uint32_t tt32_1 = *(reinterpret_cast<uint32_t*>(&(tt1[0]))) ;
    tt -= 1;
        uint32_t tt32_2 = *(reinterpret_cast<uint32_t*>(&(tt1[0]))) ;
    std::cout << tt32_1 << ' ' << tt32_2 << ' ' << (tt32_1 == tt32_2) << std::endl;

        return 0;
}
  1. clang++ 1 1 1 1 0 0 
  2. clang++ -fsanitize=address 1 1 1 1 0 0 
  3. clang++ -fsanitize=undefined 1 0 0 1 0 0 
  4. g++ 1 1 1 1 0 0 
  5. g++ -fsanitize=address 1 1 1 1 0 0 
  6. g++ -fsanitize=undefined 1 1 1 1 0 0 


Хотя вот мне удалось подобрать пример и без изменения на полпути:
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <iostream>

using std::cin;
using std::cout;

int32_t f() {
    uint64_t a = 1;
    uint32_t b = 2;
    int n;
    cin >> n;
    uint32_t* p = nullptr;
    if (n) {
        p = reinterpret_cast<uint32_t*>(reinterpret_cast<char*>(&a));
    } else {
        p = &b;
    }
    return *p;
}

int main() {
    std::cout << f() << std::endl;
    return 0;
}
(вводим 0)
  1. clang++ 1 
  2. clang++ -fsanitize=address 1 
  3. clang++ -fsanitize=undefined 1 
  4. g++ 2 
  5. g++ -fsanitize=address 1 
  6. g++ -fsanitize=undefined 1 

Т.е. gcc с оптимизацией и без санитайзера решает, что, т.к. мы уж точно не будем разыменовывать uint32_t*, указывающий на uint64_t, то равенство нулю n можно и не проверять.
Заметьте, что санитайзеры не ругаются.

 Профиль  
                  
 
 Re: c++ задача на битовые операции
Сообщение29.11.2019, 22:48 


29/12/13
306
mihaild в сообщении #1428213 писал(а):
А если его сделать совсем чуть-чуть интереснее,
Это видимо баг компилятора связанный с оптимизацией.

Никаких обоснований, что тут есть UB,( хотя бы в том виде, как например, написал Xaositect ), что происходит и откуда UB, я не вижу. Зато, я вижу строчку в рекомендациях и книге Страуструпа, что так делать можно и в одну и другую строну. Вижу, что для char, std::byte и т.п. в любом случае получается можно по стандарту.
Вижу вашу ссылку на статью хабар:
mihaild в сообщении #1428063 писал(а):
И примерно такое даже на практике
происходит - компилятор,

И нашел оригинальную статью Джон Регер, в которой речи про UB, в таком виде - нет(есть про UB в случае переполнения переменных.) И даже, напротив:
Цитата:
Q: Does the Fermat code in this post execute any signed integer overflows or other undefined behaviors?
A: I don’t believe so.


Цитата:
Update from Sat 5/1: It turns out the LLVM folks have been working on this problem lately and their latest SVN now does not contain this bug. Very nice!

Т.е. это был баг компилятора. Вижу факт, что код компилируется без ошибок и предупреждений, даже с опциями -fsanitize=undefined -pedantic.
Есть UB, нет UB ?, пускай будет, если вам так хочется... . На этом, спасибо за дискуссию, я откланиваюсь.

 Профиль  
                  
 
 Re: c++ задача на битовые операции
Сообщение29.11.2019, 23:26 
Заслуженный участник


20/08/14
11776
Россия, Москва
mihaild в сообщении #1428213 писал(а):
Т.е. gcc с оптимизацией и без санитайзера решает, что, т.к. мы уж точно не будем разыменовывать uint32_t*, указывающий на uint64_t, то равенство нулю n можно и не проверять.
Некоторые компиляторы оптимизируют данный код до inline подстановки чтения cin, сразу после чего ничего не анализируя просто выводя число 2: https://godbolt.org/z/eEwSBB - смотрите команду mov esi,2 в середине main().

Seman
Так что компилятор не является критерием соответствия кода стандарту.

 Профиль  
                  
 
 Re: c++ задача на битовые операции
Сообщение30.11.2019, 01:51 
Заслуженный участник
Аватара пользователя


16/07/14
9149
Цюрих
Seman в сообщении #1428219 писал(а):
Это видимо баг компилятора связанный с оптимизацией.
:appl: А почему у вас все опечатки любой результат работы компилятора против советской власти за вашу позицию? Т.е. работает - значит должно работать, а не работает - значит баг в компиляторе. И что у вас за баги внезапно в "лучшем валидаторе"? :mrgreen:
На самом деле тут так: работает - значит имеет право работать, не работает - значит не обязано работать.
(баги в компиляторах, конечно, встречаются, но в данном случае всё законно)
Seman в сообщении #1428219 писал(а):
Никаких обоснований, что тут есть UB, я не вижу
Я очень сочувствую вашим проблемам со зрениям, но ничем, кроме приведения еще раз ссылки на стандарт -
mihaild в сообщении #1428063 писал(а):
пункт 8.2.1.11
, помочь не могу.
Seman в сообщении #1428219 писал(а):
И нашел оригинальную статью
Джон Регер, в которой речи про UB, в таком виде - нет
Статья несколько странная, его же разъяснение лучше. Там он цитирует стандарт (компилятор имеет право считать, что цикл без побочных эффектов завершается), что, вместе с пунктом 3.27 стандарта (всё, что явно не описано в стандарте, может считаться UB) означает, что бесконечный цикл без побочных циклов - это UB.
Seman в сообщении #1428219 писал(а):
Есть UB, нет UB ?, пускай будет, если вам так хочется
Очень сильно надеюсь, что вы не пишете код ни для какой системы, с результатами работы которой я могу столкнуться.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 68 ]  На страницу Пред.  1, 2, 3, 4, 5

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group