1

メモリ内の文字列を指すcharポインタがあるとします。
その文字列をメモリ内の別の場所にコピーしたいとします。

void cpy(char **dst, char *src)
{
    *dst = (char *) realloc(*dst, strlen(src) + 1);
    memcpy(*dst, src, strlen(src) + 1);
}

(メモリ割り当てが成功し、srcNULLではないと仮定します)
この関数を次のように呼び出すとどうなりますか?

char *str = malloc(14);
memcpy(str,"hello, world!", 14);
cpy(&str,str+7);

srt今、私は文字列を指すことを期待します"world!"(私のテストではそれが行います)。
しかし、私が懸念しているのは、この呼び出しcpy*dst、実際には同じsrc文字列の異なる場所を指していることです。また、を呼び出すと、このメモリが解放される可能性があります。しかし、次の行では、その場所から。を使用してコピーしようとしています。 realloc*dstmemcpy

したがって、質問は次のとおりです。何か問題がありますか?
言い換えれば、メモリを解放してすぐに使用しても大丈夫ですか?

ありがとう。

注:reallocこの例は、で取得されたメモリで呼び出されるように更新されましたmalloc

4

2 に答える 2

9

これですべてが間違っています。etcで取得されなかったポインタを呼び出すことは完全に未定義の動作です。reallocmalloc

@Daniel Fischerが指摘しているようにmemcpy、メモリの重複領域で使用することも未定義の動作であるため(この場合はを使用する必要がありますmemmove)、注意する必要があります。


更新:大幅な編集の後、質問はまったく異なります。これは、この要約バージョンと同等になりました。

char * s = malloc(14);
strcpy(s, "hello, world!");

char * p = realloc(s, 14);

memcpy(p, s, 14);

sが成功reallocすると、が指すメモリにアクセスできなくなりp、が失敗するとが指すメモリにアクセスできないため、これも未定義の動作ですrealloc

于 2012-11-20T21:23:35.743 に答える
1

あなたの例の暗黙の仮定は、cpy割り当てなかったメモリを解放することが許可されているということです。それは一種の危険な仮定ですが、それが意図的である限り、それは問題ありません。その場合ではなく、個別mallocに使用します。freerealloc

void cpy(char **dst, char *src)
{
    // obtain completely new memory (realloc might do this anyway)
    char* new = malloc(strlen(src) + 1);

    // duplicate the string
    memcpy(new, src, strlen(src) + 1);

    // release the original memory now that we know we are done with it
    free(*dst);

    // indicate where to find the new string
    *dst = new;
}

使用しているメモリを指している他の変数を知る方法がないため、これはまだ良い考えではありませんがfree、その保証を行う方法がある場合は、これが必要な種類のコードです。

于 2012-11-20T21:40:44.467 に答える