__memcpy_sse2_unaligned-详细含义是什么? [英] __memcpy_sse2_unaligned - what does this mean in detail?

查看:192
本文介绍了__memcpy_sse2_unaligned-详细含义是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的编译器上工作时,出现此错误:

While working on my compiler I got this error:

Program received signal SIGSEGV, Segmentation fault.
__memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:33

如何获取此处发生问题的详细信息?我从回溯中知道是导致它的memcpy行,但是如何查看内存的对齐方式呢?以及我怎么知道它应该 对齐?

How do I get details of what went wrong here? I know from the backtrace it's a memcpy line that causes it, but how do I see how the memory is aligned? And how do I know how it should be aligned?

该项目是一个使用LLVM后端的编译器,它使用Zend/PHP运行时和OCaml垃圾收集器,因此很多事情都会出错.

The project is a compiler with an LLVM back-end using the Zend/PHP runtime with the OCaml garbage collector, so there's is a lot of things that can go wrong.

我怀疑这是问题的一部分:

I suspect this line being part of the problem:

zend_string *str = (zend_string *)caml_alloc(ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + len + 1), 0);

在Zend源代码中,caml_allocpemalloc.

where caml_alloc were pemalloc in the Zend source-code.

进行10'000个字符串连接时会发生段错误.这是valgrind的输出:

The segfault happens when doing 10'000 string concatenations. This is the output from valgrind:

==7501== Invalid read of size 8
==7501==    at 0x4C2F790: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7501==    by 0x4D7E58: subsetphp_concat_function (bindings.c:160)
==7501==    by 0x4D7F52: foo (llvm_test.s:21)
==7501==    by 0x4D7FA9: main (llvm_test.s:60)
==7501==  Address 0x61db938 is 2,660,600 bytes inside a block of size 3,936,288 free'd
==7501==    at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7501==    by 0x4C2627: do_compaction (in /home/olle/kod/subsetphp/test)
==7501==    by 0x4C2735: caml_compact_heap (in /home/olle/kod/subsetphp/test)
==7501==    by 0x4D08DF: caml_major_collection_slice (in /home/olle/kod/subsetphp/test)
==7501==    by 0x4D2DCF: caml_minor_collection (in /home/olle/kod/subsetphp/test)
==7501==    by 0x4D2FBC: caml_check_urgent_gc (in /home/olle/kod/subsetphp/test)
==7501==    by 0x4D7C45: subsetphp_string_alloc (bindings.c:90)
==7501==    by 0x4D7CEE: subsetphp_string_init (bindings.c:122)
==7501==    by 0x4D7DEA: subsetphp_concat_function (bindings.c:149)
==7501==    by 0x4D7F52: foo (llvm_test.s:21)
==7501==    by 0x4D7FA9: main (llvm_test.s:60)

任何提示都值得赞赏.

修改:

extern value subsetphp_concat_function(value v1, value v2) 
{

  CAMLparam2(v1, v2);

  zend_string *str1 = Zend_string_val(v1);
  zend_string *str2 = Zend_string_val(v2);
  size_t str1_len = str1->len;
  size_t str2_len = str2->len;
  size_t result_len = str1_len + str2_len;

  value result = subsetphp_string_init("", result_len, 1);
  zend_string *zend_result = Zend_string_val(result);

  if (str1_len > SIZE_MAX - str2_len) {
    zend_error_noreturn(E_ERROR, "String size overflow");
  }

  memcpy(zend_result->val, str1->val, str1_len);  // This is line 160
  memcpy(zend_result->val + str1_len, str2->val, str2_len);
  zend_result->len = result_len;
  zend_result->val[result_len] = '\0';

  CAMLreturn(result);
}

编辑2 :

因为valgrind给我这行

Since valgrind gives me this line

Address 0x61db938 is 2,660,600 bytes inside a block of size 3,936,288 free'd

我想我正在尝试复制已经释放的内容,这意味着当不再引用某些内容时,我不会正确地告诉OCaml GC.

I guess I'm trying to copy something that has already been freed, meaning that I don't tell the OCaml GC correctly when something is no longer referenced.

推荐答案

此错误告诉您在memcpy期间发生了一些不良情况,可能是空指针或大小错误.

This errors tells you that something bad happen during memcpy, probably something like a null pointer or error in the sizes.

不必担心__memcpy_sse2_unaligned,它是memcpy的实现细节. memcpy有许多针对不同情况进行了优化的不同实现,并在给定上下文的情况下动态调度到最高效的实现.当sse2指令可用且指针未分配到16个字节的边界(sse2指令无法加载未对齐的值)时,似乎可以使用该方法(可能是通过一次复制一个字节直到达到16字节的边界然后切换到快速路径.

Don't bother with __memcpy_sse2_unaligned, it is an implementation detail of memcpy. memcpy has a lot of different implementation optimized for the different cases and dispatch dynamically to the most efficient one given the context. That one seems to be used when sse2 instructions are available and pointers are not alligned to 16 bytes boundaries (sse2 instructions cannot load unaligned values), which is probably done by copying one byte at a time until a 16 byte boundary is reached then switching to the fast path.

对于与LLVM链接的OCaml gc特定细节,您需要非常谨慎地处理堆指针.由于您不知道是使用gcroot机制还是使用新的状态点,因此我假设您使用的是gcroot.

As for the OCaml gc specific details linked with LLVM, you need to be quite carefull to how you handle heap pointers. As you don't tell whether you are using the gcroot mechanism or the new statepoints, I will suppose you are using gcroot.

由于OCaml gc是移动收集器(从次要堆移动到主要堆,并在压缩期间移动),所以每个分配都可能使指针无效.这意味着将字段访问分解为堆分配的值通常是不安全的.例如,这是不安全的:

Since the OCaml gc is a moving collector (moving from minor heap to major heap, and moving during compaction) every allocation can potentially invalidate a pointer. That means that it is usualy unsafe to factorise field access to heap allocated values. For instance this is unsafe:

v = field(0, x) r = function_call(...) w = field(0, v)

v = field(0, x) r = function_call(...) w = field(0, v)

函数调用可能会进行一些分配,从而触发压缩.

the function call could do some allocations that could trigger a compaction.

v = field(0, x) r = function_call(...) v' = field(0, x) w = field(0, v')

v = field(0, x) r = function_call(...) v' = field(0, x) w = field(0, v')

顺便说一句,我什至不确定gcroot机制是否可以正确处理移动gc(该llvm不会优化它不应该做的事情).

By the way, I'm not even certain that the gcroot mechanism can correctly handle moving gc (that llvm doesn't optimize things it shouldn"t).

因此,通常,这意味着将gcroot与OCaml的GC配合使用不是一个好主意.这种新方法对这种GC更好,但是您仍然需要小心,不要在函数调用或分配之间访问指针.

So that usualy means that it's not a good idea to use gcroot with OCaml's GC. The new way is better for that kind of GC, but you still need to be carefull not to access pointer across function calls or allocations.

所以您的错误可能与这种问题有关:指针在某个时候有效,然后在压缩过程中移动了一个值,导致某个gc页未使用,因此被释放了.

So your error may be something linked to that kind of problem: the pointer was valid at some point, then a value was moved during compaction that resulted in some gc page being unused, hence freed.

这篇关于__memcpy_sse2_unaligned-详细含义是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆