한 명의 회원과 만 조합을 사용하는 목적은 무엇입니까?


89

seastar 소스 코드를 읽을 때 tx_side멤버가 하나 뿐인 공용 구조체가 있음을 알았습니다 . 이것은 특정 문제를 다루기위한 해킹입니까?

참고로 tx_side아래 구조를 붙여 넣습니다 .

union tx_side {
    tx_side() {}
    ~tx_side() {}
    void init() { new (&a) aa; }
    struct aa {
        std::deque<work_item*> pending_fifo;
    } a;
} _tx;


5
@MaxLanghof이 질문과 해당 답변은 이러한 공용체 구조를 사용하는 목적에 대해 언급하지 않았습니다.
daoliker

이 멤버를 사용하는 예가 있습니까?
n314159

4
그렇기 때문에 제 결속 투표를 실제로 사용하지 않았습니다. 그러나 나는 당신이 당신의 질문에 대한 대답에서 정확히 무엇을 기대하는지 잘 모르겠습니다. 아마도 union대신 에 사용하는 목적은 struct둘 사이의 차이점 중 하나 이상입니다. 그것은 매우 모호한 기술이므로 해당 코드의 원래 작성자가 나오지 않으면 누군가이 문제를 해결하기를 원하는 권위있는 답변을 줄 수 있는지 확실하지 않습니다.
맥스 랭 호프

2
가장 좋은 추측은 union을 사용하여 구성을 지연 (이 경우 다소 의미가 없음) 또는 pending_fifo의 파괴 (메모리 누수로 이어짐)를 방지하는 것입니다. 그러나 사용법의 예없이 말하기는 어렵습니다.
Konstantin Stupnik

답변:


82

때문에 tx_side노조는, tx_side()하지 자동으로 초기화 / 구문을 수행 a하고, ~tx_side()자동으로 소멸되지 않습니다. 이를 통해 배치 및 신규 소멸자 호출 (가난한 사람 )을 통해 a및 의 수명을 세밀하게 제어 할 수 있습니다 .pending_fifostd::optional

예를 들면 다음과 같습니다.

#include <iostream>

struct A
{
    A() {std::cout << "A()\n";}
    ~A() {std::cout << "~A()\n";}
};

union B
{
    A a;
    B() {}
    ~B() {}
};

int main()
{
    B b;
}

여기서는 구성되거나 파괴되지 B b;않기 때문에 아무것도 인쇄하지 a않습니다.

경우 B했다 struct, B()부를 것이다 A(), 그리고 ~B()부를 것이다 ~A(), 당신은 그것을 방지 할 수 없습니다.


23
@daoliker는 반드시 무작위 일 필요는 없지만 예측할 수 없습니다. 초기화되지 않은 다른 변수와 동일합니다. 무작위로 가정 할 수는 없습니다. 이전에 입력하도록 요청한 사용자의 비밀번호를 보유 할 수 있음을 알고 있습니다.
user253751

5
@daoliker : 이전 의견이 너무 낙관적입니다. 임의의 바이트는 0-255 범위의 값을 갖지만 초기화되지 않은 바이트를 읽을 경우 int얻을 수 0xCCCCCCCC있습니다. 초기화되지 않은 데이터를 읽는 것은 정의되지 않은 동작이며, 컴파일러는 단순히 시도를 취소합니다. 이것은 단지 이론이 아닙니다. 데비안은이 실수를 저지르고 OpenSSL 구현을 중단했습니다. 그들은 실제 임의 바이트를 가지고 초기화되지 않은 변수를 추가했으며 컴파일러는 "결과가 정의되지 않았으므로 0 일 수도 있습니다"라고 말했다. 제로는 분명히 더 이상 무작위가 아닙니다.
MSalters

1
@MSalters :이 소유권 주장의 출처가 있습니까? 내가 찾을 수있는 것은 그 일이 아니라는 것을 암시하기 때문에 그것을 제거 한 컴파일러가 아니라 개발자였습니다. 솔직히 컴파일러 작성자가 그렇게 나쁜 결정을 내렸다면 놀라 울 것입니다. ( stackoverflow.com/questions/45395435/… 참조 )
Jack Aidley

5
@ JackAidley : 정확한 주장은 무엇입니까? 당신은 좋은 연결을 가지고, 내가 이야기를 거꾸로 한 것 같습니다. OpenSSL은 논리가 잘못되었고 컴파일러가 합법적으로 모든 결과를 가정 할 수있는 방식으로 초기화되지 않은 변수를 사용했습니다. 데비안은 그 점을 정확히 발견했지만 문제를 해결했습니다. "나쁜 결정을 내리는 컴파일러"에 관해서는; 그들은 그런 결정을 내리지 않습니다. 정의되지 않은 동작은 잘못된 결정입니다. 최적화 프로그램은 올바른 코드에서 실행되도록 설계되었습니다. 예를 들어 GCC는 서명 된 오버플로가 없다고 가정합니다. "초기화되지 않은 데이터가 없다"고 가정하는 것도 마찬가지로 합리적입니다. 불가능한 코드 경로를 제거하는 데 사용할 수 있습니다.
MSalters

1
@JackAidley @MSalters가 내 코드에서 언급 한 것과 비슷한 문제가 발생했습니다. 초기화되지 않은 변수가 비어 있다고 잘못 가정했으며 후속 != 0비교가 참일 때 당황했습니다 . 그 후 초기화되지 않은 변수를 오류로 처리하여 해당 트랩에 다시 들어 가지 않도록 컴파일러 플래그를 추가했습니다.
톰 린트

0

간단히 말해서, 값을 명시 적으로 할당 / 초기화 하지 않으면 단일 멤버 통합 은 할당 된 메모리를 초기화하지 않습니다. 이 기능은 std:: optionalc ++ 17에서 수행 할 수 있습니다 .


2
오해의 소지가 있습니다. 멤버가 하나 뿐인 유니언은 멤버와 크기가 같습니다. 이 메모리는 멤버가 초기화 될 때까지 초기화되지 않습니다.
Kirill Dmitrenko
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.