2011-03-30 10 views
-1

コードをコンパイルして実行すると、「開始」を印刷した直後にバスエラーが発生します。ここで は何が起こるかです:Cのprintfからの論理的なバスエラー

のbash-3.2 $ ./remDup
あなたはどの文字列リテラルを変更している
バスエラー

#include <stdio.h> 
#include <string.h> 

void removeDups(char* str) 
{ 
    int len = strlen(str); 
    int i = 0; 

    for (i = 0; i < len; i++) { 
     char a = str[i]; 
     int k = i + 1; 
     int c = 0; 
     int j = 0; 

     for (j = k; j < len; j++) { 
      if (a != str[j]) { 
       str[k] = str[j]; 
       k++; 
      } else c++; 
     } 

     len -= c; 
    } 

    str[len] = '\0'; 
} 

int main(int argc, const char* argv[]) 
{ 
    char *str1 = "apple"; 

    printf("%s -> ", str1); 
    removeDups(str1); 
    printf("%s\n ", str1); 

    return 1; 
} 

答えて

4

あなたのように文字列を定義する場合:

char *str1 = "apple"; 

あなたは、内容を変更することが許可されていません - 標準は、これは(a)の未定義の動作であることは明らかです。代わりに、

char str1[] = "apple"; 

を使用して、変更可能なコピーを提供します。それと機能的に同等です:

char str1[6]; strcpy (str1, "apple"); 

(A) C99 6.4.5 "String literals"、段落6状態:

これらの配列は、それらの要素が適切な値を持って提供異なっているかどうかが指定されていません。プログラムがそのような配列を変更しようとすると、動作は未定義です。

+0

ありがとうございます。 :)しかし、なぜ私はremoveDupsを呼び出す前にバスエラーを取得するだろうか? – gfrkwiz

+2

あなたは 'removeDups'にクラッシュしています。'%s - > '' printfの出力は '\ n'を持たないため表示されません。クラッシュの前に洗い流された。 – GrahamS

4

を開始多くの場合、読み取り専用メモリに常駐します。標準では、リテラルを変更しようとすると未定義の動作であることも記載されています。あなたは文字列リテラルへのポインタを使用している場合は

、あなたは、例えばへchar str[] = "text";

変更のconst、const char * str="text";として、または配列として宣言する必要があり、次のいずれか

char str1[] = "apple"; 

この場合、コンパイラが作成されます。配列をスタックにコピーし、読み取り専用文字列リテラルをその中にコピーします。