我正在学习C并使用free()函数引导我来解决这个问题。说我有一个指针:
char *p = "String";
现在已经分配了7个字节的内存供p指向。但是,sizeof(* p)返回1,这使得它看起来像指针只知道它所拥有的地址的1字节。
如果是这种情况,那么free(p)如何释放所有7个字节。所以我能想到的唯一的事情是:
幕后发生了一些事情
只需要指定的第一个字节需要解除分配
这是其中之一吗?如果是1.什么是隐藏的过程/它是如何工作的?如果它是2.那么机器如何跟踪不应该为其他指针和变量分配的其他6个字节?
感谢您的帮助!
答案 0 :(得分:2)
sizeof(*p)
为1,因为p
指向一个字符(一个字节)。
“它怎么知道”分配的内存有多大 - 它是“平台相关的”。很多时候你会发现有关malloc的两件事:
注意 - 我上面描述的内容与使用malloc
的内存分配有关 - 这是C可以free()
的唯一类型。字符串常量以不同的方式分配,其大小和位置是固定的 - 这就是您通常编写
const char *p = "hello";
对于这样的字符串,您可以通过查找nul
终止符来了解大小。但是如果你真的决定用'\0'
覆盖字符串中较早的字符,它就不会改变分配的内存量:
char p[] = "hi there world";
p[2] = '\0';
printf("%s***\n", p);
输出:
hi***
但是内存没有被释放。
答案 1 :(得分:1)
char *p = "String";
这是合法的,但它确实应该是:
const char *p = "String";
所以你不小心尝试修改数组。
你问什么阵?任何字符串文字对应于大小为LEN+1
的静态分配数组,其中LEN
是文字的长度。所以在这种情况下,在整个程序执行期间存在一个类型为char[7]
的匿名数组,其中包含值
`{ 'S', 't', 'r', 'i', 'n', 'g', '\0' }`.
p
的初始值设定项使其指向该数组的第一个元素,其中包含'S'
。由于未通过调用malloc()
(或calloc()
或realloc()
)分配数组,因此不得尝试free()
它
给定p
,您无法直接确定数组的大小(因为p
指向其第一个元素,而不是指向整个数组)。您可以计算strlen(p) + 1
,可能与分配的大小相同 - 但如果字符串文字是"foo\0bar"
,那么它将是8个字节长,但是{{ 1}}将停在第一个空字符并返回strlen
。因此,如果您需要能够确定数组的大小,请不要通过将其地址分配给指针来丢弃该信息。
现在,如果你写了:
3
初始化程序将将字符串文字的内容复制到数组char arr[] = "String";
中,并且arr
的大小将由编译器根据初始化程序的大小确定。同样,您不得尝试在此数组上调用arr
(或者更确切地说,在指向其第一个元素的指针上),因为它未使用free()
分配。但您可以通过malloc()
轻松确定其大小,这将产生sizeof arr
。 (7
会给你一个指针的大小,而不是它指向的数组。)
最后,如果您使用sizeof p
分配数组:
malloc()
你仍然不能使用#define message "String"
char *p = malloc(sizeof message + 1);
if (p == NULL) {
fprintf(stderr, "malloc failed\n");
exit(EXIT_FAILURE);
}
strcpy(p, message);
(它只是一个指向单个字符的指针)来确定分配数组的大小 - 但是p
能够解决它。怎么样?语言没有说,但任何实现都会在幕后留下额外的簿记信息,让free()
做正确的事。
请注意,实现不一定记住您请求的大小。对free()
的调用实际上可能会分配16个字节,唯一需要的信息{基础地址和实际分配的大小。
但是,既然您已经调用了malloc(7)
,那么如果您需要记住分配的大小,只需将其保存在某处:
free
如果您有声明的数组对象,则可以使用malloc
来确定其大小。数组通常使用指针进行操作,指针不保留数组的大小;你必须自己跟踪。 // ...
const size_t allocated_bytes = sizeof message + 1;
char *p = malloc(allocated_bytes);
// ...
和朋友在幕后保留一些大小信息,但仅限于让sizeof
正常工作;你(可能)自己无法访问这些信息。如果需要跟踪已分配数组的大小,则必须自己完成。