char数组中的十六进制导致写入套接字时出现随机字符

Posted

技术标签:

【中文标题】char数组中的十六进制导致写入套接字时出现随机字符【英文标题】:Hex in char array resulting in random character when writing to socket 【发布时间】:2018-01-12 10:00:20 【问题描述】:

在与外部系统通信时,他们希望我在响应的末尾添加一个空字节。但是我面临一些问题:

//reading from socket

//sending response
std::string response = "hardcodedResponse";
int bufferSize = response.size() + 1; // +1 for the trailing zero
char buffer[bufferSize];    

for (int i = 0; i < response.size(); i++)

    buffer[i] = response[i];


buffer[bufferSize] = 0x00;

int socketfd = 1;
unsigned bytesWritten = 0;

while (bytesWritten < bufferSize)

    bytesWritten += ::write(socketfd, buffer[bytesWritten], bytesToWrite - bytesWritten);

当我使用 telnet 向套接字发送内容时,我确实收到了一个响应:“hardcodedResponse”,后跟一个▒。我认为这是有道理的,因为 0x00 为空。但是,如果我在末尾添加 0x41 (A),我会收到“hardcodedResponse”+ 一个(看似)随机字符。如果我在写入套接字之前打印缓冲区的最后一个字符,它会打印“A”。如果外部系统也接收到正确的字节,这并不重要,但可惜的是,它们接收的是随机的。

我不知道为什么会这样。希望有人能帮助我理解。

【问题讨论】:

【参考方案1】:

除了所有的套接字,看看缓冲区长度和你放置空值的位置:

std::string response = "hardcodedResponse";
int bufferSize = response.size() + 1; // +1 for the trailing zero
char buffer[bufferSize];    //Up to, but not including bufferSize
                            //0, 1, ... bufferSize-1

for (int i = 0; i < response.size(); i++)

    buffer[i] = response[i];


buffer[bufferSize] = 0x00;  //BOOM udefined behaviour

你为 null 增加了一个字符,而不是两个,所以将 null 放在末尾而不是末尾。

buffer[bufferSize-1] = 0x00;

【讨论】:

该死,我太专注于六角/插座部分,我完全没有看到。谢谢:)【参考方案2】:

首先,您依赖于称为“可变长度数组”的非标准功能。只有少数 C++ 编译器支持 VLA,并且仅作为可选扩展。您应该使用 STL std::vector 容器来代替动态大小的数组。

但是,更重要的是,您将空字节写入错误的数组索引。 buffer[] 中的有效索引范围是0..bufferSize-1。写入buffer[bufferSize] 不会在数据末尾的正确位置附加空终止符,并且会破坏周围的内存。

你需要改变这个:

buffer[bufferSize] = 0x00;

到这里:

buffer[bufferSize-1] = 0x00;

您也没有正确管理对write() 的呼叫。特别是,它可以在您没有处理的错误时返回 -1。你应该使用bufferSize 而不是bytesToWrite

话虽如此,您实际上根本不需要buffer[] 数组,您可以直接发送std::string 数据:

//sending response
std::string response = "hardcodedResponse";
const char *buffer = response.c_str();
const size_t bufferSize = response.size() + 1; // +1 for the trailing zero

size_t totalWritten = 0;
ssize_t bytesWritten;

do

    bytesWritten = ::write(socketfd, buffer[totalWritten], bufferSize - totalWritten);
    if (bytesWritten <= 0)
    
        // handle error...
        break;
    
    totalWritten += bytesWritten;

while (totalWritten < bufferSize);

或者:

//sending response
std::string response = "hardcodedResponse";
const char *buffer = response.c_str();
size_t bufferSize = response.size() + 1; // +1 for the trailing zero

size_t totalWritten = 0;
ssize_t bytesWritten;

do

    bytesWritten = ::write(socketfd, buffer, bufferSize);
    if (bytesWritten <= 0)
    
        // handle error...
        break;
    
    buffer += bytesWritten;
    bufferSize -= bytesWritten;

while (bufferSize > 0);

【讨论】:

以上是关于char数组中的十六进制导致写入套接字时出现随机字符的主要内容,如果未能解决你的问题,请参考以下文章

访问共享进程内存时出现分段错误(核心转储)

将十六进制值设置为 char 变量以进行填充时出现问题

使用 C++ 将半字写入闪存时出现 ARM Cortex-M HardFault 异常

将空数据写入非阻塞套接字会导致epoll_wait挂起

通过套接字接收数组列表时出现 NullPointerException

将 char 2d 数组转换为 2d char 数组列表时出现问题