簡體   English   中英

__memcpy_sse2_unaligned - 這是什么意思?

[英]__memcpy_sse2_unaligned - what does this mean in detail?

在處理我的編譯器時,我遇到了這個錯誤:

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

如何獲取此處出現問題的詳細信息? 我從backtrace中知道它是一個memcpy行導致它,但我如何看待內存是如何對齊的? 我怎么知道它應該如何對齊?

該項目是一個帶有LLVM后端的編譯器,使用Zend / PHP運行時和OCaml垃圾收集器,因此有很多問題可能出錯。

我懷疑這一行是問題的一部分:

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

其中caml_alloc是Zend源代碼中的pemalloc

在執行10,000個字符串連接時會發生段錯誤。 這是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給了我這條線

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

我想我正在嘗試復制已經被釋放的東西,這意味着當不再引用某些東西時我沒有正確地告訴OCaml GC。

這個錯誤告訴你在memcpy期間發生了一些不好的事情,可能類似於空指針或大小錯誤。

不要打擾__memcpy_sse2_unaligned ,它是memcpy的一個實現細節。 memcpy有很多針對不同情況優化的不同實現,並動態調度到給定上下文的最有效的實現。 當sse2指令可用且指針未分配到16字節邊界(sse2指令不能加載未對齊的值)時,似乎可以使用那個,這可能是通過一次復制一個字節直到達到16字節邊界然后切換到快速的道路。

至於與LLVM鏈接的OCaml gc特定細節,您需要非常小心如何處理堆指針。 由於您沒有告訴您是使用gcroot機制還是新狀態點,我假設您正在使用gcroot。

由於OCaml gc是一個移動收集器(從小堆移動到主堆,並在壓縮期間移動),每個分配都可能使指針無效。 這意味着將對堆分配值的字段訪問因素分解通常是不安全的。 例如,這是不安全的:

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

函數調用可以執行一些可能觸發壓縮的分配。

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

順便說一句,我甚至不確定gcroot機制是否可以正確處理移動gc(llvm不會優化它不應該的東西)。

因此,通常意味着將gcroot與OCaml的GC一起使用並不是一個好主意。 對於那種GC,新方法更好,但是您仍然需要注意不要跨函數調用或分配訪問指針。

因此,您的錯誤可能與此類問題有關:指針在某些時候有效,然后在壓縮期間移動了一個值,導致某些gc頁面未被使用,因此被釋放。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM