0

この strncpy() の実装が 2 回目の実行でクラッシュするのに、最初の実行では問題なく動作するのはなぜですか?

strncpy

文字列から文字をコピーnソースの最初の文字をコピー先にコピーします。文字がコピーされる前にソース C 文字列 (ヌル文字によって示される) の末尾が見つかった場合、合計文字数が書き込まれるnまで、destination はゼロで埋められます。n

source がこれよりも長い場合、destination の末尾に null 文字は暗黙的に追加されませんn(したがって、この場合、destination は null で終了する C 文字列ではない可能性があります)。

char *strncpy(char *src, char *destStr, int n)
{
    char *save = destStr; //backing up the pointer to the first destStr char
    char *strToCopy = src; //keeps [src] unmodified

    while (n > 0)
    {
        //if [n] > [strToCopy] length (reaches [strToCopy] end),
        //adds n null-teminations to [destStr]
        if (strToCopy = '\0') 
            for (; n > 0 ; ++destStr)
                *destStr = '\0';

        *destStr = *strToCopy;
        strToCopy++;
        destStr++;
        n--;

        //stops copying when reaches [dest] end (overflow protection)
        if (*destStr == '\0')
            n = 0; //exits loop
    }

    return save;
}

/////////////////////////////////////////////

int main()
{
    char st1[] = "ABC";
    char *st2;
    char *st3 = "ZZZZZ";
    st2 = (char *)malloc(5 * sizeof(char));


    printf("Should be: ZZZZZ\n");
    st3 = strncpy(st1, st3, 0);
    printf("%s\n", st3);

    printf("Should be: ABZZZZZ\n");
    st3 = strncpy(st1, st3, 2);
    printf("%s\n", st3);

    printf("Should be: ABCZZZZZ\n");
    st3 = strncpy(st1, st3, 3);
    printf("%s\n", st3);

    printf("Should be: ABC\n");
    st3 = strncpy(st1, st3, 4);
    printf("%s\n", st3);

    printf("Should be: AB\n");
    st2 = strncpy(st1, st2, 2);
    printf("%s\n", st2);

    printf("Should be: AB\n");
    st2 = strncpy(st1, st2, 4);
    printf("%s\n", st2);
}
4

3 に答える 3

5

セグメンテーション違反が発生するため、

char *st3 = "ZZZZZ";

宛先は文字列リテラルです。文字列リテラルは変更してはならず、多くの場合、書き込み保護されたメモリに格納されます。だからあなたが電話するとき

strncpy(st1, st3, n);

を使用するとn > 0、文字列リテラルを変更しようとしていて、クラッシュが発生します (必ずしもそうとは限りませんが、通常は)。

コピー ループで、逆参照するのを忘れているstrToCopy

if (strToCopy = '\0')

=との代わりに書き込み==strToCopyが に設定され、 のさらなる逆参照が未定義の動作をNULL引き起こします。strToCopy

于 2012-11-27T16:04:25.497 に答える
2

私はあなたがこれを望んでいないと思います:

if (strToCopy = '\0') 

代わりに、おそらくこれを行うつもりでした:

if (*strToCopy == '\0') 

一般に、yoda 条件を使用すると、比較と代入の混同の問題から頭を悩ませることが少なくなります。

if ('\0' == *strToCopy)
于 2012-11-27T16:04:06.447 に答える
0
while (n > 0)
    {
        //if [n] > [strToCopy] length (and reaches [strToCopy] end),
        //adds n null-teminations to [destStr]

        *destStr = *strToCopy;
        //stops copying when reaches [dest] end (overflow protection)
        if (*destStr == '\0')
            break; //exits loop
        strToCopy++;
        destStr++;
        n--;


    }
if (*destStr != '\0') *destStr = '\0';

概して:

printf("Should be: ZZZZZ\n");
    st3 = strncpy(st1, st3, 0);
    printf("%s\n", st3);

コピーしたい長さが0得られないため、これは間違っていますZZZZZ

于 2012-11-27T16:09:07.647 に答える