Распределение памяти в спецификациях ABI применимо только через границы ABI? - PullRequest
6 голосов
/ 31 марта 2020

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

Если "вообще" "слишком широк, рассмотрим, например, GCC / Clang с ABI System V x64 и Itanium C ++.

Вот два примера того, что я имею в виду:

  1. System V x64 ABI указывает, что массивы размером не менее 16 байтов имеют выравнивание не менее 16 байтов, даже если выравнивание типа элемента меньше и, следовательно, выровнено более строго, чем можно предположить alignof. Это также указывает, что выравнивание long double равно 16. Итак, является ли следующая функция, которая имеет неопределенное поведение в соответствии со стандартом C ++, если она вызывается, безопасна для использования в System V x86 ABI, даже если массив storage никогда не отображается через границы единицы перевода?

    void f() {
        char storage[16]; // Only guaranteed to have alignment `1` by the C++ standard.
        using T = long double;
        auto p = new(storage) T;
    }
    
  2. В Itanium C ++ ABI указывается расположение классов. Например:

    #include<new>
    
    struct A {
        int i;
        virtual ~A() {}
    };
    
    struct B : A {
        int j;
    };
    
    void f() {
        B b;
        std::launder(reinterpret_cast<A*>(&b))->i = 1;
    }
    

    f при вызове имеет неопределенное поведение по стандарту C ++, потому что B и A не являются стандартным макетом, и поэтому не определено, является ли подобъект A находится по тому же адресу, что и b, что вызывает неопределенное поведение std::launder, если это не так. Однако в Itanium C ++ ABI гарантируется, что подобъект A имеет тот же адрес, что и b, и поэтому std::launder будет успешным. Таким образом, в Itanium C ++ ABI это безопасно, даже если b никогда не передается за границы единицы перевода?

Я предполагаю, что оба моих примера безопасны, но это указано, или в ссылочных стандартах или в политиках компиляторов?

Ответы [ 2 ]

0 голосов
/ 05 апреля 2020

Вы задаете два вопроса:

[...], компиляторы вообще дают такие дополнительные гарантии? :

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

Таким образом, "обычно" слишком широкий.

При взгляде на специфику c компиляторы / платформы, ваши примеры приводят ко второму вопросу:

Будут ли мои примеры с неопределенным поведением работать на определенных платформах?

Вы уже знаете, что в примерах есть UB. Если компилятор обнаружит это, он может делать с этим кодом все, что захочет, например,

  1. отбросить все это
  2. сгенерировать код, который форматирует ваш SSD
  3. сгенерировать код это делает то, на что вы надеетесь

Проблема с UB заключается в том, что даже если сегодня ваш компилятор выберет третий вариант, нет никакой гарантии, что он сделает это снова завтра.

См. Также cppreference

Итак, ответ на второй вопрос: ну, может быть, но нет гарантии.

0 голосов
/ 02 апреля 2020

Да, согласно моим прочтениям, оба экземпляра безопасны.

Я не могу указать вам на раздел Itanium C ++ ABI, но, похоже, вы все равно твердо знаете, что он должен сказать.

Но я знаю:

Одним из возможных проявлений поведения, которое не определено в соответствии со стандартом C ++, является то, что некоторая реализация языка, такая как Itanium C ++ ABI, гарантирует определенное поведение для этой конструкции.

То есть, если в одном стандарте написано «Это не определено», а в другом стандарте написано «Это определено для выполнения Y», то, если ваши реализации соответствуют обоим стандартам, вы должны быть в состоянии предположить, что «Y "случается.

(Примечание: с другой стороны, если один стандарт говорит" Это определено для выполнения X ", а другой стандарт говорит" Это определено для выполнения Y ", то, если" X "! ​​= «Y», ваша реализация не может соответствовать обоим стандартам.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...