2015-09-11 13 views
12

私のコンパイラに取り組んでいる間、私はこのエラーを得た:__memcpy_sse2_unaligned - これはどういう意味ですか?

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

は、どのように私はここで何が悪かったのかの詳細を得るのですか?私はバックトレースから、その原因となるのはmemcpy行だと知っていますが、どのようにメモリが整列されているかは分かりますか?そして、どうすればそれがどのようにわかるのですかは整列する必要がありますか?

プロジェクトは、Zend/PHPランタイムとOCamlガベージコレクタを使用したLLVMバックエンドを持つコンパイラです。したがって、間違っていることがたくさんあります。

私は、この行が問題の一部であることを疑う:

caml_allocはZendのソース・コードに pemalloc
zend_string *str = (zend_string *)caml_alloc(ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + len + 1), 0); 

segfaultは10,000文字列の連結を行うときに発生します。これはvalgrindからの出力です:

==7501== Invalid read of size 8 
==7501== at 0x4C2F790: [email protected]@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に正しく通知しないという意味です。

+0

'subsetphp_concat_function'を表示できますか? –

+0

あなたのコード(Stackoverflowのためのものではないと主張するものもあります)のバグについて助けが必要な場合は、バグを生成するコードをできるだけ短いものにしてください。 – Thomash

+0

@ Mr.Llamaが追加されました。 –

答えて

6

このエラーは、memcpyで何か悪いことが起こったことを示しています。おそらく、サイズがnullポインタまたはエラーのようなものです。

__memcpy_sse2_unalignedを気にしないでください。memcpyの実装の詳細です。 memcpyには、さまざまなケースで最適化されたさまざまな実装があり、コンテキストに応じて最も効率的なものに動的にディスパッチします。これは、sse2命令が利用可能で、ポインタが16バイトの境界にアラインメントされていない(sse2命令はアラインされていない値をロードすることができない)ときに使用されるように思われます。これはおそらく、16バイトの境界に達するまで1バイトずつコピーし、高速パス。

LLVMにリンクされたOCaml gc固有の詳細については、ヒープポインタをどのように扱うかについては十分に注意する必要があります。 gcrootメカニズムを使用しているのか新しい状態ポイントを使用しているのか分からないので、gcrootを使用しているとします。

OCaml gcは(マイナーヒープからメジャーヒープに移動し、コンパクション中に移動する)移動コレクタなので、すべての割り当てによってポインタが無効になる可能性があります。つまり、割り当てられた値をヒープするためにフィールドへのアクセスを因数分解することは、通常危険です。例えば、これは安全ではありません:

​​

関数呼び出しは、圧縮を引き起こす可能性がいくつかの割り振りを行うことができます。ところで

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

、私はgcrootメカニズムが正しく動いてGCを扱うことができるということも、確かではないよ(つまりLLVMは、それが「T shouldn物事を最適化しません)。だからusualy手段

をOCamlのGCでgcrootを使うのは良い考えではありません。このようなGCの方が新しい方法が優れていますが、関数呼び出しや割り付けでポインタにアクセスしないよう注意する必要があります。その種の問題にリンクされた何か:ポインターがある時点で有効であった、そして値が移動したduriいくつかのgcページが使用されず、解放された結果となりました。

関連する問題