C - 从缓冲区中提取数据时出现问题。可能与字节顺序有关

标签 c

我在使用 memcpy 从缓冲区中提取数据时遇到了一些困难。

首先,我将一些变量 memcpy 到一个缓冲区中:

int l1_connect(const char* hostname, int port) {
    // Variables to be stored in the buffer
    char *msg = "Hi, I'm a message"; // strlen(msg) == 17
    uint16_t sender_id = htons(1); // sizeof(sender_id) == 2
    uint16_t packet_size = htons(sizeof(packet_size)+sizeof(sender_id)+strlen(msg)); // sizeof(packet_size) == 2

    // Checking values
    printf("l1_connect():\nsender_id: %d, packet_size: %d\n\n", ntohs(sender_id), ntohs(packet_size));
    // sender_id == 1, packet_size == 21

    // The buffer
    char buf[100];

    // Copying everything
    memcpy(&buf, &sender_id, sizeof(sender_id));
    memcpy(&buf+sizeof(sender_id), &packet_size, sizeof(packet_size));
    memcpy(&buf+sizeof(sender_id)+sizeof(packet_size), &msg, strlen(msg));

    // Passing buf to another function
    int bytes_sent = l1_send(1, buf, sizeof(buf));
}

然后我尝试提取该数据(在通过 UDP 套接字发送之前进行检查):

int l1_send( int device, const char* buf, int length ) {
    // Variables in which to store extracted data
    uint16_t id = 0;
    uint16_t size = 0;
    char msg[50];

    memcpy(&id, &buf, sizeof(id));
    memcpy(&size, &buf+sizeof(id), sizeof(size));

    int remaining = ntohs(size) - (sizeof(id) + sizeof(size));
    printf("l1_send():\nremaining: %d\n", remaining); // -37041

    // memcpy-ing with correct(?) offset
    memcpy(&msg, &buf+sizeof(id)+sizeof(size), 50);

    msg[49] = '\0';

    printf("id: %d\n", ntohs(id));      // 8372
    printf("size: %d\n", ntohs(size));  // 37045
    printf("msg: %s\n", msg);           // ��$_�

    return 0; // For now
}

如您所见,这些值并不完全符合我的预期。谁能告诉我我做错了什么?

最佳答案

你的指针数学不正确。您正在使用 &buf,而您应该只使用 buf。如果这不能解释问题所在,那么我无话可说:

#include <stdio.h>

int main(int argc, char **argv)
{
    char buff[100];
    printf("buff : %p\nbuff+10 : %p\n&buff+10 : %p\n", buff, buff+10, &buff+10);
    return 0;

}

输出(显然因平台而异)

buff : 0xbf87a8bc
buff+10 : 0xbf87a8c6
&buff+10 : 0xbf87aca4

See it live .您正在做的数学运算是按类型递增的,对于 &buf 来说,它是一个指向 100 个 char 数组的指针;不是简单的 char 地址。因此,&buff + 10(在我的示例中)说“给我从我现在所在位置开始的第 10 个 100 个字符的数组。”。结果,后续写入将调用未定义的行为。

Valgrind顺便说一句,你的 friend 在这儿吗?它会立刻捕捉到这一点。


更新

不妨在我在这里的时候填写整个开局。这在 l1_send 中也是错误的:

memcpy(&id, &buf, sizeof(id));
// this------^

以及您在该函数中使用它的后续其他区域。您正在获取参数指针的地址,而不是其中的值。我相信您在那里也需要 buf

关于C - 从缓冲区中提取数据时出现问题。可能与字节顺序有关,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21839514/

相关文章:

c - 在单链表的开头插入节点

c - 刽子手游戏错误

c - 嵌入式编译不喜欢 char *var[]= {"data","data"};

c++ - -DXXX 编译器参数的 CMAKE 选项

c++ - 如果任一参数为 NaN,什么会导致 C/C++ <、<= 和 == 运算符返回 true?

c - scanf() 在以前工作正常时导致段错误

c - 如何在 vigenere cipherkey cs50 pset2 中重用(循环) key

c - FFTW 库 : how to properly plot an output?

c - 迭代可能的信号列表

c - 为什么在二维数组中 a 和 *a 指向相同的地址?