2014-04-07 2 views
7

내 질문은 인라인 C 코드와 관련이 있습니다. 인라인 스택 함수 (Inline_Stack_Vars)를 사용하여 변수를 전달해야합니까? in/out 또는이 문맥에서 변수를 수정하는 것이 적절합니까?Perl 인라인 :: C : 메모리 누수를 피하기 위해 Inline_Stack_Vars 등이 필요합니다 (생체 인식 문자 일치)

생체 인식 데이터를 표시하려면 두 개의 정렬 된 문자열 사이에 차이점 만 표시해야합니다. 예 : 주어진 두 문자열 :.. 내가 '으로의 대체 두 번째 문자열이 (일치하는 문자를 얻으려면

ATCAGAAA--GACATGGGCCAAAGATTAA-CAGTGGCCATTGACAGGA-- 
    --CCCCAACTGACAGGGGGCAAAGATTAA-CAGTGGCCATTG---GGA-- 

--.CCC..CT....G...G..........-............---...-- 

나는 (수백만 Illumina의 읽기의 순서를 많이 가지고 .)는, 그래서 다음 인라인 코드는 장소에 add_matchchars 기능)에 두 번째 인수를 변경 (잘 작동하는 것 같다 캐릭터 매칭 :: 인라인 C를 돌았 다 :

#!/usr/bin/perl 
use Inline C; 

my($seq1,$seq2) = qw/ ATCAGAAA--GACATGGGCCAAAGATTAA-CAGTGGCCATTGACAGGA-- 
         --CCCCAACTGACAGGGGGCAAAGATTAA-CAGTGGCCATTG---GGA-- /; 

print $seq1,"\n"; 
print $seq2,"\n"; 
add_matchchars($seq1,$seq2); 
print $seq2,"\n"; 

__END__ 

__C__ 

void add_matchchars(char *seq1, char *seq2) { 
    int seq1char; 
    int seq2char; 
    while(seq1char = *seq1++ , seq2char = *seq2++) { 
     if (seq1char == seq2char) { 
      *seq2--; 
      if (seq1char != '-') { 
       *seq2 = '.'; 
      } 
      *seq2++; 
     } 
     //printf("%c-%c\n",seq1char,seq2char); 
    } 
// printf("%s\n%s\n",seq1,seq2); 
} 

그러나 1) 내가있다 합리적으로 효율적 (더 똑똑한/더 나은 방법이 있습니까?)? 2) 메모리가 누출됩니까?

+0

'Inline_Stack_ *'은 가변 길이 인자 목록에 접근하는 수단이다 .. 메모리 누출과 아무런 관련이 없다 .. – ikegami

+0

Inline_Stack _은 매개 변수를 전달할 때 일반적으로 사용되는 더 낮은 수준의 매크로를 대신하여 사용할 수있는 매크로이다. Perl XS를 사용하여 호출 스택에서 앞뒤로 이동하는 것이 편리합니다. 매개 변수 호출 스택에 액세스하는 경우 일반적으로이 매크로를 사용하거나 낮은 수준의 XS 매크로 세트 – DavidO

답변

6

수정할 수있는 스칼라 또는 스칼라의 원래 버퍼 인 char *에 의존해서는 안됩니다. 대신 새 문자열을 반환하십시오.

Inline_Stack_Vars 매크로는 가변 개수의 인수 또는 여러 개의 반환 값을 처리 할 때만 유용합니다. 여기의 경우도 마찬가지입니다.

코드가 현재 메모리 누수가 없습니다 (C 함수 내에 메모리를 할당하지 않음). 그러나 몇 가지 문제가 있습니다. . 스타일, 가능한 세그먼테이션 폴트 (segfault) (올바른 while((seq1char = *seq1++) && (seq2char = *seq2++))-while(seq1char = *seq1++ , seq2char = *seq2++) 펄 문자열이 문자열 내에서 NUL을을 포함 할 수 있다는 사실

나는 일반적으로 당신의 C 함수를 직접 스칼라을 가지고 더 좋은 아이디어라고 생각 대략 :.

SV *add_matchchars(SV *seq1_sv, SV *seq2_sv) { 
    STRLEN len1, len2; 
    char *seq1 = SvPVbyte(seq1_sv, len1); 
    char *seq2 = SvPVbyte(seq2_sv, len2); 
    STRLEN min_len = len1 < len2 ? len1 : len2; 
    SV *seq3_sv = newSVpvn(seq2, min_len); 
    char *seq3; 
    STRLEN i; 

    seq3 = SvPVX(seq3_sv); 
    for (i = 0; i < min_len; ++i) { 
     if (seq1[i] == seq2[i]) 
      seq3[i] = '.'; 
    } 

    return seq3_sv; 
} 
+1

감사합니다. 편집에 대한 ikegami, 나는 그들로부터 많은 것을 배웠습니다. – amon

+0

np. '$ seq2'를 내부에서 수정하고 싶다면'SvPVbyte' 대신'SvPVbyte_force'를 사용하고'seq3'를 수정하는 대신'seq2'를 수정하십시오. – ikegami

+0

감사합니다. @amon - 이런 종류의 피드백은 내가 필요한 것입니다. – user3507704