web-dev-qa-db-ja.com

再割り当て後、バッファ内のデータが失われますか?

Reallocのしくみを理解できません。バッファをmallocして、そのバッファにデータをコピーした場合、「AB」としましょう。

 +------------+
 | A | B | \0 |
 +------------+

次に、バッファを再割り当てしましたが、データが失われますか(1バイトでも)?;それともバッファを拡張するだけですか? :

 +------------------------+
 | A | B | \0 | ? | ? | ? |
 +------------------------+

コード:

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

int main(void){

    char* buffer    = (char*) malloc( sizeof(char) * 3 );
    strncpy(buffer, "AB", 2);

    buffer          = (char*) realloc(buffer, sizeof(char) * 6); /* Will there be any lost here? */
    free(buffer);
    return(0);
}
34
user1129665

ブロックのサイズを増やすreallocは、元のメモリブロックの内容を保持します。メモリブロックのサイズを変更できない場合でも、古いデータは新しいブロックにコピーされます。ブロックのサイズを縮小するreallocの場合、古いデータは切り捨てられます。

reallocの呼び出しは、何らかの理由でreallocが失敗した場合にデータを失うことを意味することに注意してください。これは、reallocNULLを返すことで失敗するためですが、その場合、元のメモリブロックは引き続き有効ですが、ポインタを上書きしたため、アクセスできなくなりますNULL

標準パターンは次のとおりです。

_newbuffer = realloc(buffer, newsize);
if (newbuffer == NULL)
{
    //handle error
    return ...
}
buffer = newbuffer;
_

また、Cではmallocからの戻り値のキャストは不要であり、sizeof(char)は定義により_1_と等しいことに注意してください。

53
David Heffernan

何も失われません。ただし、realloc()(および以前のmalloc())が「機能する」かどうかを実際にテストする必要があります。
また、mallocの戻り値へのキャストは、せいぜい冗長であり、コンパイラーが存在しない場合にキャッチしたエラーを隠す可能性があります。

文字列が必要であるという前提に基づいて、strncpyの使用が間違っています

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

int main(void) {
    char *buffer = malloc(3);
    if (buffer == NULL) /* no memory */ exit(EXIT_FAILURE);

    strncpy(buffer, "AB", 2);
    /* ATTENTTION! ATTENTION: your array is not a string.
    ** buffer[2] is not the zero string terminator */

    // buffer = realloc(buffer, 6); /* Will there be any lost here? */
    /* If realloc returns NULL, you've just lost the only pointer to
    ** the allocalted memory, by overwriting it with NULL.
    ** Always `realloc` to a temporary variable */
    char *tmp_buffer = realloc(buffer, 6);
    if (tmp_buffer == NULL) {
        /* realloc failed */
    } else {
        /* realloc worked, no bytes lost */
        buffer = tmp_buffer;
        /* ATTENTION! ATTENTION: buffer is still not a string
        ** buffer[0] is 'A', buffer[1] is 'B',
        ** all other elements of buffer are indeterminate */
    }

    free(buffer);
    return(0);
}
5
pmg