1

我认为这是一个非常直接的问题,但我仍然无法弄清楚。

我有通过网络发送流的功能。自然,这需要 const void * 作为参数:

void network_send(const void* data, long data_length)

我正在尝试在通过套接字发送之前以 char* 的形式在其前面添加一个特定的标头:

  long sent_size = strlen(header)+data_length;
  data_to_send = malloc(sent_size);
  memcpy(data_to_send,header,strlen(header)); /*first copy the header*/
  memcpy((char*)data_to_send+strlen(header),data,dat_length); /*now copy the actual data*/

只要数据实际上是 char* ,它就可以正常工作。但如果它更改为其他一些数据类型,那么这将停止工作。

接收时,我需要在处理之前从数据中删除标题。所以它是这样做的:

void network_data_received(const void* data, long data_length)
{
 ........
 memmove(data_from_network,(char*)data_from_network + strlen(header),data_length); /*move the data to the beginning of the array*/
 ProcessFurther(data_from_network ,data_length - strlen(header)) /*data_length - strlen(header) causes the function ProcessFurther to read only certain part of the array*/
}

如果数据是 char 类型,这又可以正常工作。但如果它是任何不同的类型就会崩溃。

谁能建议如何正确实施?

问候,汗

4

6 回答 6

2

听起来对齐可能是问题所在,但您没有指定要在哪个平台上执行此操作(不同的 CPU 架构有不同的对齐要求)。

如果标头的长度对于以下数据的对齐是“错误的”,则可能导致访问冲突。

于 2010-12-07T12:24:18.477 回答
2

这段代码让我感到惊讶。你的标题实际上是一个字符串吗?如果它是一个类似的结构,你应该用 sizeof 替换 strlen。在非零终止字符串上调用 strlen 可能会导致崩溃。

让我吃惊的第二件事是,在读取接收到的数据时,您应该将标头复制到某处。如果不使用它,为什么还要通过电线发送它?

编辑:好的,标头是一些类似 http 的标头字符串。从那里应该没有任何问题,如果只是测试,确实不需要分析。

而且您应该将数据移动到您实际需要的位置,将其移动到缓冲区的开头看起来不是正确的做法。

如果问题来自对齐,如果您在使用它之前将数据复制到字节级别的实际目标类型的某个变量中,它将消失。

还有另一种解决方案:使用 malloc 分配缓冲区并将所需的数据结构放在开头。然后你应该可以施放它。malloc 返回的地址与任何类型兼容。

另请注意,如果您使用的是 C++,则转换为非平凡的类不太可能起作用(一方面,vtable 可能会得到错误的地址,还有其他问题)。

另一个可能的问题来源是您获取 data_length 的方式。它应该是多个字节。你确定不是物品数量?为了确保我们需要一些调用代码的提示。

于 2010-12-07T12:28:08.777 回答
0

memcpy如果您应该使用的源和目标重叠(如本例中),则 的行为未定义memmove()

当什么不是时,究竟发生了什么char*?这些函数通常会void*在实际执行任何工作之前转换为...

于 2010-12-07T12:22:48.030 回答
0

调用代码中可能data_length未正确计算。否则,除了@unwind 提到的可能的对齐问题之外,这段代码似乎很好。

如何header声明?它有可变长度吗?您是否在 之后缺少终止NUL字符header

于 2010-12-07T12:30:05.403 回答
0

我还要检查以确保发送者和接收者都使用相同的字节排序架构(小端与大端)。

于 2010-12-07T18:40:56.990 回答
0

使用unsigned char * 解决了这个问题。谢谢大家的意见。

于 2010-12-09T04:14:30.043 回答