1

「セグメンテーション違反...」が発生する理由と、このコードでそれを修正する方法を誰かが説明してもらえますか?

#include<stdio.h>

int str_length(char *s) {
    int length = 0, i;
    for(i = 0; *s; i++) {
        s++;
    }
    return i;
}

char *strdel(char *s, int pos, int n) {
    int i;
    char *p, str[] = "";
    p = str;
    for(i = 0; i < str_length(s) - n + 1; i++)  {
        if(i >= pos) {
            *(p + i) = *(s + i + n);
        }
        else {
            *(p + i) = *(s + i);
        }
    }
    s = str;
    return s;
}

int main() {
    char *str = "abcdef";
    printf("str_lengh: %d\n", str_length(str));
    printf("strdel: %s\n", strdel(str, 1, 2));
    return 0;
}

そして、私はこの出力を取得します:

str_lengh: 6
strdel: adef
Segmentation fault (core dumped)

また、関数を作成するより良い方法はありますか: char *strdel(char *s, int pos, int n); それは私がしたものより位置 pos から n 文字を削除しますか?

4

3 に答える 3

5

ここのスタック全体に書いていると思います...

char *strdel(char *s, int pos, int n) {
    int i;
    char *p, str[] = "";
    p = str; // p points to str which is "" and is on the stack with length 0.
    for(i = 0; i < str_length(s) - n + 1; i++)  {
        if(i >= pos) {
            *(p + i) = *(s + i + n); // now you are writing onto the stack past p
        }
        else {
            *(p + i) = *(s + i);// now you are writing onto the stack past p
        }
    }
    s = str; // now s points to space on stack
    return s; // now you return a pointer to the stack which is about to disapear 
}

多くの場合、p を超えて書き込むと、未定義の動作が発生します。UB ヒープまたはスタックに割り当てられていない領域に書き込みを行っています。

s のみで動作するバージョンの strdel を作成できます。私が strdel を正しく理解している場合、このようなもの: (大まかに、テストされていません!、 pos と n の境界チェックが必要です)

char *strdel(char *s, int pos, int n) {
    char *dst = s + pos, *src = s + pos + n;
    while(*src) {
        *dst++ = *src++;
    }
    *dst = 0;
    return s;
}
于 2013-10-31T00:38:24.810 に答える
2

2番目の部分でも私のソリューションを投入します。これが私のstrdel

char * strdel(char * s, int pos, int n){ 
    memmove(s + pos, s + pos + n, strlen(s) - pos - n + 1); 
    return s;
}

コピーせず、境界チェックも行わず、戻り値はかなり冗長です (入力と等しいためs)。全体として、非常に標準的な C ライブラリに似ています。

警告!変更されるため、文字列定数には使用できませんs(したがって no const char * s)。

于 2013-10-31T00:55:49.130 に答える
0

質問の 2 番目の部分に対処するには、次のように記述します (文字列定数を渡すため、受信文字列のコピーを作成する必要があると仮定します)。

/*
 * Returns a copy of the NUL terminated string at s, with the
 * portion n characters long starting at position pos removed.
 */
char* strdel(char* s, int pos, int n)
{
    int size = strlen(s);
    char* t = malloc(size - n);
    memcpy(t, s, pos);
    memmove(t + pos, s + pos + n, size - n + 1);
    return t;
}
于 2013-10-31T00:47:23.710 に答える