2

我有这个StructType st = StructTypeSecondInstance->st;,它会产生一个段错误。奇怪的部分是堆栈回溯向我显示:

0x1067d2cc: memcpy + 0x10 (0, 10000, 1, 1097a69c, 11db0720, bfe821c0) + 310
0x103cfddc: some_function + 0x60 (0, bfe823d8, bfe82418, 10b09b10, 0, 0) +

那么,结构赋值使用memcpy吗?

4

4 回答 4

5

一个说不出来。小型结构甚至可以保存在寄存器中。是否memcpy使用是一个实现细节(它甚至不是实现定义的,或者未指定的——它只是编译器编写者选择的东西,不需要记录。)

从 C 标准的角度来看,重要的是在分配之后,目标结构的结构成员比较等于源结构的相应成员。

我希望编译器编写者在速度和简单性之间做出权衡,可能基于结构的大小,越大越有可能使用memcpy. 一些memcpy实现非常复杂,并根据长度是否为 2 的幂或 src 和 dst 指针的对齐方式使用不同的算法。为什么要重新发明轮子或使用内联版本破坏代码memcpy

于 2012-09-13T10:02:07.527 回答
2

它可能,是的。

这应该不足为奇:结构赋值需要尽快将一堆字节从一个地方复制到另一个地方,这恰好memcpy()是应该擅长的事情。如果您是编译器编写者,那么生成对它的调用似乎很容易。

请注意,这意味着分配具有大量填充的结构的效率可能低于最佳效率,因为memcpy()无法跳过填充。

于 2012-09-13T09:56:14.480 回答
1

该标准根本没有说明编译器如何实际实现赋值(或任何其他运算符)。没有什么可以阻止编译器(比如说)为源文件中的每个操作生成函数调用。

编译器有权按照它认为最好的方式实现分配。大多数时候,对于大多数平台上的大多数编译器,这意味着如果结构相当小,编译器将生成内联的移动指令序列;如果结构很大,调用 memcpy 是很常见的。

但是,编译器循环生成随机位域并在其中一个与分配源匹配时停止是完全有效的(我们将此算法称为 bogocopy)。

如果您的目标平台没有可用(或完整)libc,则支持非托管操作的编译器通常会为您提供关闭发出此类 libcall 的开关。

于 2012-09-13T10:23:09.967 回答
0

这取决于编译器和平台。大对象的赋值可以使用memcpy。但这一定不是段错误的原因。

于 2012-09-13T09:56:48.793 回答