我在Linux中使用std::pair
和read()
函数在命名管道上传递write()
。我通过引用传递它,并通过引用阅读它。这是怎么回事?据我所知,std::pair
未被序列化,当引用超出范围时会发生什么。是可以移动对象,还是通过引用复制?
我很困惑。
我是C ++的新手,所以我的指针和参考知识有点差,但据我所知,我通过管道传递地址,然后将读取端对象指向这个新地址。
虽然读取侧对象是一个对象,而不是一个指针。那么它的旧/原始实例会发生什么?
我正在使用此代码编写:
std::pair<int, somestruct> sample_pair;
write(FD, &sample_pair, sizeof(sample_pair));
使用此代码阅读:
std::pair<int, somestruct> sample_pair;
read(FD, &sample_pair, sizeof(sample_pair));
答案 0 :(得分:1)
您根本没有通过管道发送std::pair
的地址。您正在发送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));
或者,它可能很复杂,在发送之前必须将somestruct
的内容展平为顺序byte[]
数组,例如:
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);
或者,您可以单独发送值:
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);