2017-04-20 7 views
0

리눅스에서 read()write() 함수를 사용하여 명명 된 파이프를 통해 std::pair을 전달했습니다. 나는 이것을 참고로 통과 시켰고 그것을 참고로 읽었다. 어떻게 작동 했습니까? 내가 아는 바로는 std::pair이 직렬화되지 않으며 레퍼런스가 범위를 벗어날 때 어떻게됩니까? 개체를 이동할 수 있습니까? 또는 참조로 복사 할 수 있습니까?명명 된 파이프를 통해 std :: pair를 전송 한 이유는 무엇입니까?

혼란 스럽습니다.

저는 C++을 처음 사용하기 때문에 포인터와 참조 지식이 조금 부족하지만 파이프를 통해 주소를 전달하고 읽은 개체를이 새 주소로 가리키고 있습니다.

읽기 측 객체는 물론 객체이지만 포인터가 아닙니다. 그러면 이전 인스턴스/원래 인스턴스는 어떻게됩니까?

std::pair<int, somestruct> sample_pair; 
write(FD, &sample_pair, sizeof(sample_pair)); 

을 그리고이 코드를 사용하여 읽기 :

이 코드를 사용하여 작성하고 당신은 모든 파이프를 통해 std::pair주소를 전송하지 않습니다

std::pair<int, somestruct> sample_pair; 
read(FD, &sample_pair, sizeof(sample_pair)); 

답변

1

. 실제 (std::pair)을 보내고 있습니다.

std::pair 인스턴스의 주소를 시작 주소로 write()으로 전달하여 sizeof(sample_pair) 바이트의 초기 주소에서 시작하여 파이프로 순차적으로 씁니다. 따라서 std::pair 내부에 저장된 원시 바이트는 파이프 위에있는 그대로 쓰여집니다.

시작 주소로 std::pair 인스턴스의 주소를 read()으로 전달하고 파이프에서 sizeof(sample_pair) 바이트 수를 읽고 해당 초기 주소에 순차적으로 저장하도록 알려줍니다. 파이프로부터 수신 된 로우 바이트는 따라서 std::pair 내부에 저장됩니다.

std::pair을 이런 식으로 보내는 것은 아직 정의되지 않은 동작입니다. std::pair의 실제 메모리 레이아웃은 구현에 따라 다르며 특히 두 필드 사이에있을 수있는 정렬 패딩과 관련하여 특히 그렇습니다. 데이터를 수동으로 프로세스 경계를 ​​넘어서는 안전한 형식으로 직렬화 한 다음 반대쪽에서 역 직렬화해야합니다.예컨대

그것은 개별적 개의 필드를 전송하는 것만 큼 간단 할 수있다 (somestruct 가정 자 급식 (외부 데이터없이 포인터) 및 자체의 정렬에 문제가 없다), 예 :

#pragma pack(push, 1) 
struct somestruct 
{ 
    int8_t value1; 
    int16_t value2; 
    int32_t value3; 
    char data[256]; 
}; 
#pragma pack(pop) 

std::pair<int32_t, somestruct> sample_pair; 
// populate as needed... 

write(FD, &(sample_pair.first), sizeof(sample_pair.first)); 
write(FD, &(sample_pair.second), sizeof(sample_pair.second)); 

std::pair<int32_t, somestruct> sample_pair; 

read(FD, &(sample_pair.first), sizeof(sample_pair.first)); 
read(FD, &(sample_pair.second), sizeof(sample_pair.second)); 

또는,이 같은 복잡 할 수있다 당신은 단지 개별적으로 값을 보낼 수,

struct somestruct 
{ 
    int8_t value1; 
    int16_t value2; 
    int32_t value3; 
    std::string data; 
}; 

std::pair<int32_t, somestruct> sample_pair; 
// populate as needed... 

std::vector<uint8_t> buffer(
    sizeof(int32_t) + 
    sizeof(int8_t) + 
    sizeof(int16_t) + 
    sizeof(int32_t) + 
    sizeof(int32_t) + 
    sample_pair.second.data.length() 
); 

uint8_t *ptr = &buffer[0]; 

*reinterpret_cast<int32_t*>(ptr) = htonl(sample_pair.first); 
ptr += sizeof(int32_t); 

*reinterpret_cast<int8_t*>(ptr) = sample_pair.second.value1; 
ptr += sizeof(int8_t); 

*reinterpret_cast<int16_t*>(ptr) = htons(sample_pair.second.value2); 
ptr += sizeof(int16_t); 

*reinterpret_cast<int32_t*>(ptr) = htonl(sample_pair.second.value3); 
ptr += sizeof(int32_t); 

*reinterpret_cast<int32_t*>(ptr) = htonl(sample_pair.second.data.length()); 
ptr += sizeof(int32_t); 

std::copy(sample_pair.second.data.cbegin(), sample_pair.second.data.cend(), reinterpret_cast<char*>(ptr)); 

int32_t len = htonl(buffer.size()); 
write(FD, &len, sizeof(len)); 
write(FD, buffer.data(), buffer.size()); 

std::pair<int32_t, somestruct> sample_pair; 

int32_t len; 
read(FD, &len, sizeof(len)); 
len = ntohl(len); 

std::vector<uint8_t> buffer(len); 
uint8_t *ptr = &buffer[0]; 

read(FD, ptr, len); 

sample_pair.first = ntohl(*reinterpret_cast<int32_t*>(ptr)); 
ptr += sizeof(int32_t); 

sample_pair.second.value1 = *reinterpret_cast<int8_t*>(ptr); 
ptr += sizeof(int8_t); 

sample_pair.second.value2 = ntohs(*reinterpret_cast<int16_t*>(ptr)); 
ptr += sizeof(int16_t); 

sample_pair.second.value3 = ntohl(*reinterpret_cast<int32_t*>(ptr)); 
ptr += sizeof(int32_t); 

len = ntohl(*reinterpret_cast<int32_t*>(ptr)); 
ptr += sizeof(int32_t); 

sample_pair.second.data.assign(reinterpret_cast<char*>(ptr), len); 

을 또는 : 차 예를 들어, 보내기 전에 순차적 byte[] 배열로 somestruct의 내용을 평평하게하는 데 :

void sendInt8(int FD, int8_t value) 
{ 
    write(FD, &value, sizeof(value)); 
} 

void sendInt16(int FD, int16_t value) 
{ 
    value = htons(value); 
    write(FD, &value, sizeof(value)); 
} 

void sendInt32(int FD, int32_t value) 
{ 
    value = htonl(value); 
    write(FD, &value, sizeof(value)); 
} 

void sendStr(int FD, const std::string &value) 
{ 
    sendInt32(FD, value.length()); 
    write(FD, value.c_str(), value.length()); 
} 

... 

std::pair<int32_t, somestruct> sample_pair; 
// populate as needed... 

sendInt32(FD, sample_pair.first); 
sendInt8(FD, sample_pair.second.value1); 
sendInt16(FD, sample_pair.second.value2); 
sendInt32(FD, sample_pair.second.value3); 
sendStr(FD, sample_pair.second.data); 

int8_t readInt8(int FD) 
{ 
    int8_t value; 
    read(FD, &value, sizeof(value)); 
    return value; 
} 

int16_t readInt16(int FD) 
{ 
    int16_t value; 
    read(FD, &value, sizeof(value)); 
    return ntohs(value); 
} 

int32_t readInt16(int FD) 
{ 
    int32_t value; 
    read(FD, &value, sizeof(value)); 
    return ntohl(value); 
} 

std::string readStr(int FD) 
{ 
    std::string value; 
    int32_t len = readInt32(FD); 
    if (len > 0) 
    { 
     value.resize(len); 
     read(FD, &value[0], len); 
    } 
    return value; 
} 

... 

std::pair<int32_t, somestruct> sample_pair; 

sample_pair.first = readInt32(FD); 
sample_pair.second.value1 = readInt8(FD); 
sample_pair.second.value2 = readInt16(FD); 
sample_pair.second.value3 = readInt32(FD); 
sample_pair.second.data = readStr(FD);