Вопросы по тегу: abi

(3)

Why can a T* be passed in register, but a unique_ptr<T> cannot?

I'm watching Chandler Carruth's talk in CppCon 2019: There are no Zero-Cost Abstractions in it, he gives the example of how he was surprised by just how much overhead you incur by using an std::unique_ptr over an int*; that segment starts about at time point 17:25. You can have a look at the compilation results of his example pair-of-snippets (godbolt.org) - to witness that, indeed, it seems the compiler is not willing to pass the unique_ptr value - which in fact in the bottom line is just an address - inside a register, only in straight memory. One of the points Mr. Carruth makes at around 27:00 is that the C++ ABI requires by-value parameters (some but not all; perhaps - non-primitive types? non-trivially-constructible types?) to be passed in-memory rather than within a register. My questions: Is this actually an ABI requirement on some platforms? (which?) Or maybe it's just some pessimization in certain scenarios? Why is the ABI like that? That is, if the fields of a struct/class fit within registers, or even a single register - why should we not be able to pass it within that register? Has the C++ standards committee discussed this point in recent years, or ever? PS - So as not to leave this question with no code: Plain pointer: void bar(int* ptr) noexcept; void baz(int* ptr) noexcept; void foo(int* ptr) noexcept { if (*ptr > 42) { bar(ptr); *ptr = 42; } baz(ptr); } Unique pointer: using std::unique_ptr; void bar(int* ptr) noexcept; void baz(unique_ptr ptr) noexcept; void foo(unique_ptr ptr) noexcept { if (*ptr > 42) { bar(ptr.get()); *ptr = 42; } baz(std::move(ptr)); }
e

einpoklum

2 года назад

Ответов: 4

Безопасно ли связывать объекты C ++ 17, C ++ 14 и C ++ 11

Предположим, у меня есть три скомпилированных объекта, все они созданы одним и тем же компилятором / версией: A был скомпилирован со стандартом C ++ 11 B был скомпилирован по стандарту C ++ 14 C был скомпилирован со стандартом C ++ 17 Для простоты предположим, что все заголовки были написаны на C ++ 11, с использованием только конструкций, семантика которых не изменилась между всеми тремя стандартными версиями, и поэтому любые взаимозависимости были правильно выражены с включением заголовка и компилятор не возражал.Какие это комбинации этих объектов и небезопасно ли объединить их в один двоичный файл? Почему?РЕДАКТИРОВАТЬ: приветствуются ответы, касающиеся основных компиляторов (например, gcc, clang, vs ++)
r

ricab

4 года назад

Ответов: 3

Допускает ли стандарт C ++ использование неинициализированного bool для сбоя программы?

Я знаю, что "неопределенное поведение" в C ++ может в значительной степени позволить компилятору делать все, что он хочет. Однако у меня произошел сбой, который меня удивил, так как я предполагал, что код достаточно безопасен.В этом случае настоящая проблема возникла только на определенной платформе с использованием определенного компилятора и только в том случае, если была включена оптимизация.Я пробовал несколько вещей, чтобы воспроизвести проблему и максимально упростить ее. Вот отрывок из функции под названием Serialize, которая принимает параметр типа bool и копирует строку true или false в существующий целевой буфер.Была бы эта функция при проверке кода, не было бы никакого способа сказать, что она действительно могла бы дать сбой, если бы параметр bool был неинициализированным значением?// Zero-filled global buffer of 16 characters char destBuffer[16]; void Serialize(bool boolValue) { // Determine which string to print based on boolValue const char* whichString = boolValue ? "true" : "false"; // Compute the length of the string we selected const size_t len = strlen(whichString); // Copy string into destination buffer, which is zero-filled (thus already null-terminated) memcpy(destBuffer, whichString, len); } Если этот код выполняется с оптимизацией clang 5.0.0 +, он будет / может вылететь.Ожидаемый тернарный оператор boolValue? «true»: «false» выглядело для меня достаточно безопасным, я предполагал: «Какое бы значение мусора ни было в boolValue, это не имеет значения, поскольку оно в любом случае будет оцениваться как true или false» *. 100006 *Я установил пример Compiler Explorer, который показывает проблему при разборке, здесь полный пример.Примечание: чтобы воспроизвести проблему, я обнаружил, что сработала комбинация с использованием Clang 5.0.0 с оптимизацией -O2.#include #include // Simple struct, with an empty constructor that doesn't initialize anything struct FStruct { bool uninitializedBool; __attribute__ ((noinline)) // Note: the constructor must be declared noinline to trigger the problem FStruct() {}; }; char destBuffer[16]; // Small utility function that allocates and returns a string "true" or "false" depending on the value of the parameter void Serialize(bool boolValue) { // Determine which string to print depending if 'boolValue' is evaluated as true or false const char* whichString = boolValue ? "true" : "false"; // Compute the length of the string we selected size_t len = strlen(whichString); memcpy(destBuffer, whichString, len); } int main() { // Locally construct an instance of our struct here on the stack. The bool member uninitializedBool is uninitialized. FStruct structInstance; // Output "true" or "false" to stdout Serialize(structInstance.uninitializedBool); return 0; } • 100001 , который должен технически быть либо 0, либо 1, и выглядит так:const size_t len = strlen(whichString); // original code const size_t len = 5 - boolValue; // clang clever optimization Хотя это, так сказать, «умно», у меня вопрос: Позволяет ли стандарт C ++ компилятору предполагать, что bool может иметь только внутреннее числовое представление '0' или '1' и использовать его таким образом?Или это случай, определяемый реализацией, и в этом случае реализация предполагала, что все ее bools всегда будут содержать только 0 или 1, а любое другое значение является неопределенной территорией поведения?
R

Remz

3 года назад

Ответов: 5

2022 WebDevInsider