2

可能重复:
C 数组实例化 - 堆栈或堆分配?

当动态分配包含 char 指针的结构时,实际的 char 指针会发生什么情况?它存储在哪里?

一旦结构被释放,char 指针是否也随之被释放?

例如考虑以下结构:

struct mix
{
    int a;
    float b;
    char *s;
};

typedef struct mix mix;

然后为它分配内存的以下代码:

int main()
{
    mix *ptr = (mix*)malloc(sizeof(mix));

    ptr->a = 3;
    ptr->b = 4.5f;
    ptr->s = "Hi, there, I'm just a really long string.";

    free(ptr);

    return 0;
}

在堆栈上分配,*s然后与? *ptr我可以想象它确实是在堆栈上分配的,因为它不是以任何方式动态分配的(除非 malloc 有一些我不知道的功能)。而且我想“超出范围”*s将是释放的点*ptr。还是我完全错了?:)

非常感谢!

4

6 回答 6

6

char*命名成员的空间与调用后s的其余成员一起在堆上分配(您不需要转换其返回值)。分配给的字符串文字不是在堆或堆栈上分配的,而是实际二进制文件的一部分并具有静态存储持续时间。所以这:mixmalloc()s

ptr->s = "Hi, there, I'm just a really long string.";

将字符串文字的地址分配给ptr->s. 如果你想ptr->s指向字符串文字以外的东西,那么你需要malloc()记住它。并且对于每一个都malloc()必须有一个free()soptr->s需要在 isfree()之前是 d ptr(如果ptr->s只是指向动态分配内存)。

在调用 之后free(),取消引用ptr是未定义的行为。

于 2012-10-18T09:23:12.367 回答
4

当您使用 动态分配mixmalloc(),您实际上是在分配一块内存来存储mix结构数据成员,即

  • 一个int( a)
  • 一个float( b)
  • 指向( char)的s指针

当你打电话时free(),你只需释放那个块。

所以,你不分配字符串,你只分配字符串指针

如果要动态分配字符串,则必须显式执行(通过另一个调用malloc()),并且为避免内存泄漏,您还应该显式释放字符串,使用free().

于 2012-10-18T09:24:26.223 回答
4

当您 malloc for 时ptr,将为结构的所有成员分配内存,包括与为结构s的任何其他成员分配的内存没有什么不同的指针。

您正在为 分配一个字符串文字s,所以它通常存储在只读部分中很好。否则,您还需要mallocforptr->sfree. 因为,它是一个字符串文字,所以这里没有必要释放s(这样做是 UB)。

于 2012-10-18T09:24:28.267 回答
2

mix* ptr在栈上分配。ptr 指向的内容,mix 类型的变量,在堆上动态分配,包括指针s

请注意,s它没有指向任何东西,指针没有做任何有用的事情。您必须将其设置为指向可以分配到任何地方的东西。当你的结构被释放时,它指向的任何东西都不会被释放。在这种情况下,您将其设置为指向在 ROM 中分配的常量字符串文字,因此您无需担心这一点。

于 2012-10-18T09:25:17.447 回答
2

*s 是否在栈上分配

*s(即,取消引用指针的结果s)根本没有分配。malloc,之后ptr->s是一个未初始化的指针。它不指向任何东西,并且表达式*(ptr->s)具有未定义的行为,直到您执行ptr->s = "Hi, etc".

一旦您初始化ptr->s指向字符串文字,*(ptr->s)它就是字符串文字的第一个字符,因此它可能存在于可执行文件的某些数据部分中。sizeof(mix)除了结构的字节(在 32 位实现上可能是 12 个字节)之外,没有任何东西是动态分配的。

于 2012-10-18T09:34:59.073 回答
2
what happens with the actual char pointer? Where is it stored? 

char* 也和其他成员一样,占用一些字节(在 64 位机器中占用 8 个字节,类似于其他指针)。在您的情况下,您正在为堆中的该结构实例分配内存。因此该指针的内存也将分配在为该结构实例分配的同一堆块中。

考虑这段代码。这给出了 char* 的位置:

#include <stdio.h>    
typedef struct
{
    int a;
    float b;
    char *s;
}mix;    
int main()
{

printf("\n%d ,float:%d, int:%d, char*:%d", sizeof(mix), sizeof(float), sizeof(int), sizeof(char*));

return 0;
}

所以这个结构的大小是 16 字节。由 4 字节整数、4 字节浮点数和 8 字节字符*组成。(在 64 位操作系统中,如果操作系统为 32 位,则 char* 将为 4 个字节。)

And once the struct is freed, is the char pointer freed along with it?

通常 char* 指向的块不会被释放(如果它指向 malloc() 分配的块)。只有结构块将被释放。我们知道 free() 需要在分配期间返回的有效地址以进行和平解除分配。如果您在没有释放该 char* 的情况下释放,则会导致内存泄漏。

但是你的情况"Hi, there, I'm just a really long string.";

上面给出的字符串是在程序的只读部分中分配的字符串文字。

采用gcc -S Yourprogram.c

这将生成 .s 文件。您可以查看.read_only此字符串的部分。所以即使你删除了你的结构实例,也不会有内存泄漏。因为您只是指向一个只读地址。您根本没有为此字符串分配内存。

于 2012-10-18T09:46:22.927 回答