C 中的 ( void * ) 前缀和删除
我认为这是一个非常简单的问题,但我仍然无法弄清楚。
我有通过网络发送流的功能。当然,这需要 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 类型,这又可以正常工作。但如果它是任何不同类型,则会崩溃。
谁能建议如何正确实施这一点?
问候, 汗
i think this is a pretty straight forward problem , but i still can not figure it out .
I have function which sends stream over the network . naturally , this takes const void * as argument:
void network_send(const void* data, long data_length)
i am trying to prepend a specific header in the form of char* to this before sending it out over the socket:
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*/
This works fine as long as the data is actually char* . but if it changes to some other data type , then this stops working .
when receiving , i need to remove the header from the data before processing it . so this is how it do it:
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*/
}
This again works ok if the data is char type . but crashes if it is of any different type .
Can anyone suggest how to properly implement this ?
Regards,
Khan
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
听起来对齐可能是问题,但您没有指定在哪个平台上执行此操作(不同的 CPU 架构有不同的对齐要求)。
如果标头的长度对于后续数据的对齐来说是“错误的”,则可能会导致访问冲突。
Sounds like alignment could be the issue, but you don't specify which platform you're doing this on (different CPU architectures have different alignment requirements).
If the header's length is "wrong" for the alignment of the following data, that could cause access violations.
这段代码中有些东西让我感到惊讶。你的标题实际上是一个字符串吗?如果它是一个类似的结构,您应该将 strlen 替换为 sizeof。对非零终止字符串调用 strlen 可能会导致崩溃。
让我惊讶的第二件事是,在读取接收到的数据时,您应该将标头复制到某处。如果不使用它,为什么还要通过网络发送呢?
编辑:好的,标头是一些类似http的标头字符串。从那里应该没有任何问题,如果你只是测试的话确实不需要分析。
而且您应该将数据移动到实际需要的位置,将其移动到缓冲区的开头看起来不是正确的做法。
如果问题出在对齐上,那么如果在使用数据之前将数据复制到字节级别的真实目标类型的某个变量中,问题就会消失。
还有另一种解决方案:使用 malloc 分配缓冲区并将所需的数据结构放在开头。然后你应该能够投射它。 malloc 返回的地址与任何类型兼容。
另请注意,如果您使用 C++,则转换为不平凡的类不太可能起作用(一方面,vtable 可能会得到错误的地址,并且还有其他问题)。
另一个可能的问题根源是获取 data_length 的方式。它应该是多个字节。您确定这不是一些物品吗?为了确保我们需要一些调用代码的提示。
Something surprise me in this code. Is your header actually a string ? If it is a struct, of something similar you should replace strlen with sizeof. Calling strlen on non zero terminated string is likely to cause crashes.
The second thing that surprise me is that when reading received data, you should copy the header somewhere. If not using it, why bother sending it over the wire ?
EDIT: OK, the header is some http like header string. There should not be any problem from there, and it indeed does not need to be analysed if you're just testing.
And you should move the data to the place you actually need it, moving it to the beginning of the buffer does not look like the right thing to do.
If the problem comes from alignment, it will disappear if you copy the data to some variable of the real target type at byte level before using it.
There is another solution: allocate your buffer with malloc and put the data structure you want at the beginning. Then you should be able to cast it. Addresses returned by malloc are compatible with any type.
Also be aware that if you were working with C++, casting to a non-trivial class is unlikely to work (for one thing vtables are likely to get a wrong addresses, and there is other issues).
Another possible source of problem is the way you get data_length. It should be a number of bytes. Are you sure it is not a number of items ? To be sure we need some hint of the calling code.
如果源和目标重叠(如本例所示),则 memcpy 的行为是未定义的,您应该使用 memmove() ,
当不发生时到底发生了什么字符*?这些函数通常会在实际执行任何工作之前转换为
void*
...memcpy
's behaviour is undefined if the source and target overlap (as in this instance) you should be usingmemmove()
What exactly is happening when what is not
char*
? These functions will generally cast tovoid*
before actually doing any work...调用代码中可能未正确计算
data_length
。否则,除了@unwind提到的可能的对齐问题之外,这段代码似乎没问题。header
是如何声明的?它有可变长度吗?您是否在header
之后缺少终止NUL
字符?It's possible that
data_length
is not calculated correctly in the calling code. Otherwise this code seems to be fine apart from possible alignment issues mentioned by @unwind.How is
header
declared? Does it have variable length? Are you missing a terminatingNUL
character after theheader
?我还会检查以确保发送方和接收方都使用相同的字节排序架构(小端字节序与大端字节序)。
I'd also check to make sure that both sender and receiver use the same byte ordering architecture (little endian vs. big endian).
使用
unsigned char *
解决了这个问题。谢谢大家的评论。using
unsigned char *
solved the issue . thankyou all for your comments.