2014-04-07 20 views
7

我的問題涉及到工作內聯C代碼:是否需要使用內聯堆棧函數(Inline_Stack_Vars)來傳遞變量進出,還是在這種情況下適當地修改一個變量是適當的?Perl Inline :: C:Inline_Stack_Vars等需要避免內存泄漏(生物序列字符匹配)

對於顯示生物序列數據,我需要顯示兩個對齊的字符串之間的差異;例如鑑於這兩個字符串:。

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

我想用」的替換第二個字符串中得到這個(在匹配字符

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

我有很多的序列(百萬Illumina的讀),所以紛紛轉向內聯::下的字符匹配以下聯的代碼似乎只是正常工作(改變的第二個參數來代替add_matchchars功能):

#!/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函數中分配任何內存),但會出現一些問題。 。風格,可能就是內存設計缺陷(正確while(seq1char = *seq1++ , seq2char = *seq2++)while((seq1char = *seq1++) && (seq2char = *seq2++))和Perl的字符串可能包含字符串內完全無效的事實

我認爲這通常是一個更好的主意,有你的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_force'而不是'SvPVbyte',然後修改'seq2'而不是修改'seq3'。 – ikegami

+0

謝謝@amon - 這種反饋正是我所需要的。 – user3507704