3

コードのセグメンテーション違反が発生し、その理由がわかりません。

 1  #include <stdio.h>
 2
 3  void overwrite(char str[], char x) {
 4    int i;
 5    for (i = 0; str[i] != '\0'; i++)
 6      str[i] = x;
 7  }
 8
 9  int main(void) {
10    char *s = "abcde";
11    char x = 'X';
12    overwrite(s, x);
13    printf("%s\n", s);
14    return 0;
15  }

gdbデバッガーは、問題が6行目にあり、charをc-stringに格納したい場所にあることを教えてくれます(左辺値ポインターの逆参照を使用する場合、それは同じ問題です)。これは彼が言うことです:

(gdb) run
Starting program: /tmp/x/x 

Breakpoint 1, overwrite (str=0x8048500 "abcde", x=88 'X') at x.c:5
5         for (i = 0; str[i] != '\0'; i++)
(gdb) s
6           str[i] = x;
(gdb) 

Program received signal SIGSEGV, Segmentation fault.
0x080483e3 in overwrite (str=0x8048500 "abcde", x=88 'X') at x.c:6
6           str[i] = x;
(gdb) q

私は K&R-C の本から学んでおり、これは 2.8 章 (削除機能) の単純化された例です。どこに問題があるのか​​ わかりません。

4

5 に答える 5

17

char * s = "abcde"; 読み取り専用メモリに文字列を作成します。試す

char s[] = "abcde";

編集:説明:char *はポインタであり、「abcde」は読み取り専用メモリ->不変に作成されます。

char []は配列であり、完全にスタックに格納され、メモリから初期化されるため、変更可能です。

于 2009-09-10T14:29:27.347 に答える
2

文字列リテラルへのポインタを定義するときは、として宣言しconst char *ます。

const char *s = "abcde";

そうすれば、その文字列を overwrite() 関数に送信しようとすると、コンパイラが文句を言います。

const char *s = "abcde";
char t[] = "fghij";
char x = 'X';

overwrite(s, x); /* oops */
overwrite(t, x); /* ok */
于 2009-09-10T14:54:26.337 に答える
1

同意しませんが、詳しく説明します。コンパイラがこれを許可した場合にどうなるかを考えてください。あなたは書くことができます:

char *s1="abcde";
char *s2="abcde";
s1[0]='x';
puts(s1);
puts(s2);

コンパイラが 2 つのリテラルが同じであることを認識して再利用するが、3 行目も許可する場合、出力は次のようになります。

xbcde
xbcde

これはおそらくあなたが望むものではありません。これは、2 つのリテラルがプログラムの大きく離れた部分にある場合、特に不可解です。

于 2009-09-10T15:10:35.943 に答える
-1

試してみる:

#include <iostream>
#include <cstring>

using namespace std;

void overwrite(char[], char);

int main(void)
{
        char *s = strdup("abcde");
        char X = 'X';
        overwrite(s, X);
        cout << s << endl;

        if(s!=NULL)
                delete [] s;

        return 0;
}

void overwrite(char str[], char x)
{
        for(int i=0; str[i]!='\0'; i++)
                str[i] = x;
}
于 2009-09-10T15:11:59.093 に答える
-2

私の推測では、型を文字の配列として定義するパラメーター定義です。charへのポインタを渡している間

最初の行を次のように変更してみてください。

 void overwrite(char *str, char x) {

char配列とcharポインターは意味的に同じではありません。

于 2009-09-10T14:31:04.617 に答える