2009-08-18 15 views
2

このコードはうまくコンパイルされますが、実行中にセグメンテーションフォールトエラーが発生しますか?なぜ誰に言えますか?Cでの単純な文字列ランタイムエラー?

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

int main() { 
    const char s2[] = "asdfasdf"; 
    char* s1; 

    strcpy(s1, s2); 
    printf("%s", s1); 

    return 0; 
} 
+0

コードをコンパイルしても、安定したプログラムが保証されるわけではありません。コンパイラは*いくつかのチェックを行いますが、少なくともC言語ではないすべての危険なプログラムを排除する方法はありません。他の多くの言語ははるかに保護されていますが、ほとんどの場合、方法Cは行う。 – quark

答えて

13

あなたは、単一のポインタs1のためのスペースが割り当てられますが、バイトがs1によって指しません。

s1 = (char *)malloc(strlen(s2) + 1); 
strcpy(s1, s2); 

あなたは文字の数よりも(mallocへの呼び出しで1)メモリの1つの以上のバイトを割り当てる必要があることに注意してください:

ソリューションは、動的にs1にメモリを割り当てることですs2最後に暗黙のNULLバイトがあるためです。

詳細については、C Memory Management (Stack Overflow)を参照してください。

+1

s2は静的に割り当てられた配列なので、sizeof()を使ってnul-terminatorを含むサイズを取得できます。もちろん、strlen()+ 1は一般的な場合には正しいです。 –

+1

ここで私が答えを混乱させたくないヒントをいくつか挙げておきます:1)_Do_は 's1!= NULL'をチェックし、2)_Do_は即座に返されないコードで' s1'に 'free'を呼び出します。 –

+0

また、ポインタ 's1'は、初期化されていないため確定できません。初期化時には、文字列を格納するのに十分な領域を指している必要があります。スペースは 'malloc()'から来るかもしれません。それは他の場所から来るかもしれません。 –

4

s1にメモリを割り当てていません。あなたはs1へのポインタを持っていますが、strcpyがs2の値をコピーするために割り当てられたメモリはありません。

char *s1 = malloc(strlen(s2) + 1); 

strcpy(s1, s2); 
+2

あなたのmalloc呼び出しにoff-by-oneエラーがあります。 –

+0

'strcpy'は2つの引数しか取らない。たぶんあなたは 'strncpy'を考えているかもしれません。 –

+0

Andrew、ありがとうございました。 ああ、あなたは正しいSeanさん、修正するように編集します。 – nathan

1

宛先を割り当てる必要があります(using namespace std;はCではなくC++で、残りのコードはCです)。

2

問題は、s1に関連付けられているメモリがないことです。 strcpymalloc()を呼び出しません。

次のいずれかを行うことができます:

char s1[10];

または

char *s1 = malloc(10);

+2

しかし、それをサポートするシステムでstrdupは行います。 :-) –

3

あなたはS1に任意のメモリを割り当てられていません。これは何も指すことのないポインタです。

char* s1 = malloc(sizeof(s2)); 
strcpy(s1, s2); 
printf("%s", s1); 
free(s1); 
+2

s2が配列であるため、sizeof(s2)が機能することに注意してください。ポインタの場合は、strlen(s2)+1が必要です。 – AProgrammer

0

ポインタs1にメモリを割り当てる必要があります。あなたがそれをしなければ、それは未知のどこかを指しているでしょう、そして、こうしてセグメンテーション違反に到着します。正しいコードは次のとおりです。

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

int main() { 
    const char s2[] = "asdfasdf"; 
    char* s1 = malloc(21 * sizeof(s2[0])); 
    strcpy(s1,s2); 
    printf("%s",s1); 
    return 0; 
} 
+1

sizeof(char)== 1が標準によって保証されているので、sizeof(char)は必要ありません。これはCであり、voidポインタは他の種類のポインタに暗黙的に変換可能であるため、(char *)キャストは必要ありません。 –

+0

@Tyler McHenry申し訳ありませんが、私は学校でそれが必要であることを学んだ。とにかく、sizeof部分については、私はそれがそこにあるはずだと思います。 – Guilherme

+1

そして、それを 'sizeof(s2 [0])'または 'sizeof(* s2)'にしてください –

2

s1のスペースを割り当てる必要があります。うまく動作するかを誰も投稿しています、しかし、あなたは既存の文字列のためのスペースを割り当てるための簡単な方法をしたいし、新しいポインタにそれをコピーした場合、このようstrdupの使用:

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

using namespace std; 

int main() { 
    const char s2[] = "asdfasdf"; 
    char* s1; 

    s1 = strdup(s2); 
    printf("%s", s1); 

    return 0; 
} 

誰かがのstrdup先に述べたように、それはそれを使う方法になります。ほとんどのシステムは、標準ライブラリに入っているので、それをサポートする必要があります。しかし、明らかにいくつかはしません。したがって、エラーが返された場合は既に述べた方法で自分自身を書いてください。既に述べた方法を使用してください;)

2

この問題に対処するためのstrdup(String Duplicate)の可能性はまだ指摘されていません。

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

using namespace std; 

int main() { 
    const char s2[] = "asdfasdf"; 
    char* s1; 

    s1 = strdup(s2); // Allocates memory, must be freed later. 
    printf("%s", s1); 

    free(s1);   // Allocated in strdup, 2 lines above 
    return 0; 
} 
関連する問題