2017-08-23 5 views
-1

3つの問題がありますが、それらは本質的に同じだと思います。C - 3文字列を返そうとしたときのセグメンテーションフォールトの問題

私は、パラメータとして取得する文字列上で何かをしている3つの関数を持っていますが、結果を返そうとすると、毎回セグメンテーションフォルトが発生し、なぜ理解できません。

/* the function gets a string, and return the string without blank spaces (is exists) in the end of the string */ 
char *trimRightSpaces(char *str, unsigned int len) 
{ 
    unsigned int i = len; 
    char *trimStr = NULL; 

    if(str == NULL) 
     return NULL; 

     while(i > 0) 
    { 
     if(isspace((int)str[i])) 
        break; 
     i--; 
    } 

    strncpy(trimStr, str, i-1); 
    trimStr[i+1] = '\0'; 
    return trimStr; 
} 

と、この機能は付き文字列だけです私のプログラムからラベルを取得します ':' 文字を最後に:

/* The function gets a pointer to a string, and returns the name of label without ':' if it's a valid label, NULL if not. */ 
char *isLabel(char *str) 
{ 
    int i; 
    char tempStr[80]; 

    if(str == NULL) 
     return NULL; 

    if(strlen(str) > VALID_LABEL_LENGTH) 
     return NULL; 

    for(i = 0; i < strlen(str); i++) 
    { 
     if(i == 0) 
     { 
      /* if the first letter of the string is not small or capital letter, then it's not a valid label. */ 
      if(!isalpha((int)str[0])) 
       return NULL; 
     } 

     if(i == (strlen(str) - 1)) 
     { 
       if((int)str[i] != ':') /* check it the word ends with ':', otherwise it's not a valid label */ 
        return NULL; 
       break; 
     } 

     if(!isalnum((int)str[i])) 
      return NULL; 
    } 

    strncpy(tempStr, str, strlen(str) - 1); 

    if(isLanguageWord(tempStr)) 
     return NULL; 

    return str; 
} 

と:関数内

/* the function get a string, and check if it's a valid string: a string inside " ". if it's valid, it returns the string without " ", and NULL otherwise. */ 
char *validString(char *str) 
{ 
    char temp[80]; 
    char *temp2 = NULL; 
    int i; 

    if(str == NULL) 
     return NULL; 

    if(str[0] != '"' || str[strlen(str) - 1] != '"') 
     return NULL; 

    for(i = 1; i < strlen(str) - 1; i++) 
    { 
     temp[i] = str[i]; 
    } 
    temp2 = temp; 
    return temp2; 
} 
+4

を否定する必要がありますか? – Bathsheba

+2

最初の文字列はありません。それは割り当てられておらず、ただNULLポインタです。残りの部分を調べるのは怠惰ですが、明らかにポインタを使って作業することについて知っていることを修正する必要があります。 –

+3

'char * trimStr = NULL; ... strncpy(trimStr、str、i-1); ' - >無効な場所にデータを書き込もうとしています。 – chux

答えて

1

char *validString(char *str) 

次の文:

temp2 = temp; 

は、ポインタがローカル変数を指すように設定しています。

はこの文:

return temp2; 

は、そのポインタを返しています。

問題は、ローカル変数が「スコープ外になる」(関数が終了したときに発生する)という問題です。スタック変数は使用できなくなります。

呼び出し関数内のその変数の内容にアクセスすることは、未定義の動作です。

I.E.実際に末尾のスペースをトリムすることはありませんtrimRightSpaces()validString()関数と同じ問題を抱えている:

/* the function get a string, and check if it's a valid string: a string inside " ". if it's valid, it returns the string without " ", and NULL otherwise. */ 
char *validString(char *str) 
{ 
    if(str == NULL) 
     return NULL; 

    if(str[0] != '"' || str[strlen(str) - 1] != '"') 
     return NULL; 

    return strdup(str); 
} // end function: validString 

機能:機能はに減少させることができます。提案:

/* the function gets a string, and return the string without blank spaces (is exists) in the end of the string */ 
char *trimRightSpaces(char *str) 
{ 
    if(str == NULL) 
     return NULL; 

    size_t i; 
    for(i = strlen(str); i > 0 && ' ' == str[i]; i--); 

    char *trimstr = strdup(str); 

    if(trimstr) 
     trimstr[i] = '\0'; // note: this may need to be [i+1] 

    return trimstr; 
} // end function: trimRightSpaces 

機能:islabel()は同じ問題およびその他のいくつかの問題を抱えています。提案:

/* The function gets a pointer to a string, and returns the name of label without ':' if it's a valid label, NULL if not. */ 
char *isLabel(char *str) 
{ 
    if(str == NULL) 
     return NULL; 

    if(strlen(str) > VALID_LABEL_LENGTH) 
     return NULL; 

    if(isLanguageWord(str)) // note: this 'may' not work, but function not posted so don't know 
     return NULL; 

    if(str[strlen(str) -1] != ':') /* check it the word ends with ':', otherwise it's not a valid label */ 
     return NULL; 

    /* if the first letter of the string is not small or capital letter, then it's not a valid label. */ 
    if(!isalpha((int)str[0])) 
     return NULL; 

    for(size_t i = strlen(str); i ; i--) 
    { 
     if(!isalnum((int)str[i])) 
      return NULL; 
    } 

    return strdup(str); 
} // end function: isLabel 
+0

注:この行は' for (i = 0と&& "== str [i]; i--);'は、文字列中に(少なくとも)1つの空白以外の文字があると仮定しています。 – user3629249

+0

これらの関数が返す文字列を 'free'する必要があります – pm100

0

コードにはさまざまな問題があります。例えば

、あなたdeclateポインタが

char *trimStr = NULL; // Points to NULL, cant dereference 
char *trimStr;   // Uninitialized ptr, cant dereference 

をcharへの場合は、あなたはNULLまたは初期化されていないポインタデリファレンス傾きます。さらに悪いことに、内部でデータをコピーしようとしています。あなたがしなければならないことは、あなたがtrimStrにlenバイトをコピーすることができます例えば

char *trimStr = malloc(len); 

、ヒープに十分なメモリを割り当てることです。

第2に、validStringのようにローカル変数へのポインタを返すことができません。プログラムカウンタが関数から返ってきて、フレームが破棄され、ローカル変数がスコープから外れています - >これ以上到達できません。ヒープ上に割り当てられたメモリへのポインタを返すか、配列へのポインタを渡す必要があります。

はまた、私はあなたがスペースをトリミングする

if(isspace((int)str[i])) 

ようないくつかの論理問題を見ることができますが、そのスペースであれば非ゼロがisspace返します。だから、表現デュースがあなたの最初のスニペットで、 `trimStr`用に割り当てられたメモリである

if(!isspace((int)str[i])) 

Here is the example of trimRightSpaces function.

関連する問題