【问题标题】:Copying data of an unknown type into an array in C将未知类型的数据复制到C中的数组中
【发布时间】:2014-07-07 01:23:16
【问题描述】:

我有一个函数,它接收分配在堆上的未知类型的数据,我想将它复制到数组中的特定位置。问题是这个函数不能访问数据的类型;只是它的地址和大小。

这是函数可以访问的信息:

unsigned int count; /* length of the array */
unsigned int pos; /* index in the array */
void *data; /* source data */
size_t elemsize; /* sizeof data type */
void *array = malloc(elemcount * elemsize);

我已经达到的解决方案是使用 memcpy 并将数组转换为 char* 以便能够在字节级别上对其进行寻址。

memcpy((char*) array + elemsize * pos, (char*) data, elemsize);

但是,我了解到在某些架构中使用带有未对齐指针的 memcpy 时可能出现的问题。

将源数据转换为 char* 是否会使此操作安全?

在任何情况下,通过将数组转换为 char* 来寻址数组(即sizeof(char) != 1 的任何系统)或以这种方式使用 memcpy 可能会导致问题?

【问题讨论】:

  • 你不能不小心尝试在未对齐的数据上使用memcpy(),因为它的参数有最低对齐要求,也就是_Alignas(char)。只有第一次转换是必需的,因为void* 上的指针算术是编译错误。第二个是多余的。
  • 我添加了第二个演员表,因为我读到了一些关于 ARM Compilers handle memcpy 的信息。
  • 代码对malloc() 的调用为array 返回了一个对齐良好的指针。对于大小为elemsize所有类型array 已正确对齐。 memcpy() 在指针上工作,就好像它们是 char * - 在这里很好地使用 (char*) array + elemsize * pos 没有问题。查看 ARM 链接,发现它推荐 char * cast。根据 C 规范,还没有看到为什么需要强制转换。
  • @JoãoPinheiro 有趣的链接。但是,这里的链接似乎讨论了从指针类型推断对齐 - 也就是说,如果您出于某种原因执行int *foo = array 之类的操作,那么它将假定 4 字节对齐。在这种情况下不适用
  • @chux A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned57) for the pointed-to type, the behavior is undefined. (6.3.2.3) :)

标签: c arrays memory memcpy memory-alignment


【解决方案1】:

将源数据转换为 char* 是否会使此操作安全?

这没什么区别。

是否存在通过将数组转换为 char*(即 sizeof(char) != 1 的任何系统)或以这种方式使用 memcpy 来寻址数组的任何情况?

没有带有sizeof(char) != 1 的系统。标准规定必须是1

使用memcpy 永远不会有任何问题,只要不超出正在读写的对象的边界,并且目标是可写的,并且对象不重叠。特别是没有任何对齐问题。

(当您尝试访问您复制到的对象时可能会出现问题,如果您没有成功地为该对象建立有效的表示)。

我已了解在某些架构中使用带有未对齐指针的 memcpy 时可能出现的问题。

要么您误解了您阅读的内容,要么信息有误。如果您在讨论链接的 ARM 文章中的代码:

void example (unsigned int * const unaligned_ptr)
{

如果unaligned_ptr 没有与unsigned int 正确对齐,则在执行进入函数体之前,行为已经未定义。该页面似乎提供了一种尝试从未定义行为中恢复的方法。恕我直言,这是一个相当糟糕的主意,最好不要一开始就发起未定义的行为;或者检测它,然后抛出某种致命异常,以便可以调试和纠正问题。

【讨论】:

  • 你的意思是事先检测出来,因为事后为时已晚。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-06
  • 1970-01-01
  • 1970-01-01
  • 2011-08-10
  • 2011-07-25
  • 1970-01-01
相关资源
最近更新 更多