当分配给另一个变量时,C 中结构中的 malloced 数据会发生什么情况?

What happens to malloced data in a struct in C when it is assigned to another variable?

假设我有一个名为“example”的结构,它有一个名为 data 的成员,用于存储在堆上分配的数据:

typedef struct _EXAMPLE
{
    signed char *data;
    size_t size;
} example_t;

example_t *example_alloc(size_t size)
{
    example_t *ret = malloc(sizeof *ret);
    ret->size = size;
    ret->data = calloc(size, sizeof *ret->data);

    return ret;
}

example_t *a = example_alloc(10), b = *a;

b.data中的值是存放在栈中还是堆中?是否指向a中的数据?

指针只是值。

b.size 只是 a->size 的副本相同,b.dataa->data 持有的相同指针值的副本。

它指向同一个位置,无论它在哪里。

必须小心,因为 freeing a->data 会使 b.data 无效,反之亦然,如果访问可能会导致 Undefined Behavior

结构 b 是一个局部变量,它的所有成员都存储在本地堆栈中(请不要迂腐地评论说 C 没有指定有一个堆栈——它需要一些东西就像一个堆栈)。

因为 b.datab 的成员,它存储在堆栈中。但是它指向的数据和a->data指向的是一样的,就是函数中用calloc()分配的堆内存

正在关注 b = *aa->data == b.data。也就是说,它们都引用相同的已分配内存。这被称为“浅拷贝”。要在 C 中实现 “深度复制” 需要额外的代码。例如:

example_t* example_copy( example_t* b, const example_t* a )
{
    *b = *a ; // shallow copy all members
    
    // Allocate new block and copy content
    size_t sizeof_block = b->size * sizeof(*b->data)
    b->data = malloc( sizeof_block ) ;
    memcpy( b->data, a->data, sizeof_block ) ;

    return b ;
}

然后

example_t *a = example_alloc(10) ;
example_t b ;
example_copy( &b, a ) ;

请注意,此类代码极易发生内存泄漏。例如,如果 bb.data 成为 free 之前超出范围,您将无法访问该内存。任何在没有 free 的情况下分配内存和 returns 的函数都使它成为调用者的责任,而根本没有使它必然可见或明显(您的命名约定 _alloc 是某种程度的也许缓解)。你至少也应该实现相应的功能来方便对象的clean-up。我很欣赏这是一个 off-topic 点,但 C++ 提供了一个解决方案来解决这个问题,即当对象超出范围时调用析构函数。此外,复制构造函数和赋值运算符重载可用于自动调用 deep-copy 语义。