使用函数 malloc() 和 free(),初始化指针出现问题

using function malloc() and free(), problems with initialized pointer

提问人:mariekart42 提问时间:6/19/2022 最后编辑:chqrliemariekart42 更新时间:6/19/2022 访问量:175

问:

我对编码并不陌生,但我遇到了一个我无法向自己解释的问题。

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

int main()
{
    char    *test;

    test = (char *)calloc(15, sizeof(char));
    // test = "Wurstbrot";
    free(test);
}

如果我编译这个,就会被错误定位并直接释放(我所期望的)。 但是,如果我取消注释注释,则在编译时会出现此错误:test

a.out(28953,0x104403dc0) malloc: *** error for object 0x10365cfae: pointer being freed was not allocated
a.out(28953,0x104403dc0) malloc: *** set a breakpoint in malloc_error_break to debug
zsh: abort      ./a.out

当我删除该功能时,它将再次工作。free

我现在的问题是:为什么释放初始化的指针在这里有问题?

C Malloc 自由 Calloc

评论

2赞 Weather Vane 6/19/2022
在 C 语言中,你不能复制字符串(初始化除外)。请使用 .您正在用指向字符串文本的指针覆盖从中获取的指针,该字符串文本无法传递给该字符串文本,因为它不是从 或 获取的。同时,从调用 to 中获取的指针值将丢失,并且无法释放(悬空)。=strcpycallocfreecallocmalloccalloc
1赞 mariekart42 6/19/2022
@WeatherVane谢谢你,但你能解释一下你的最后一句话吗,你说的“迷路”是什么意思
1赞 Weather Vane 6/19/2022
您从中获取了一个指针,然后用其他指针替换了该指针,因此原始值将丢失。这意味着您分配的内存是不可能的,因为您不再知道指针值。“丢失”与“丢失”的意义相同,如果您更改联系人列表中的电话号码,则以前的号码将丢失。你不再拥有它。callocfree

答:

2赞 chqrlie 6/19/2022 #1

free必须向 、、 或其他堆分配函数分配的块传递空指针或有效指针。malloc()calloc()realloc()strdup()

如果取消注释,则指针将指向静态数据,字符串文字 .将此地址传递给具有未定义的行为。test = "Wurstbrot";"Wurstbrot"free()

传递未初始化也会有未定义的行为。如果幸运的话,这个未初始化的变量可能恰好包含一个空指针,因此不会导致...未定义的行为是未定义的,任何事情都可能发生,包括没有可见的副作用。运行时错误(例如 C 库报告的错误)实际上对于查找错误非常有用。事后看来,没有副作用可能不是运气。testfree()

0赞 ssd 6/19/2022 #2

当我们一步一步地分析程序运行时:

A) 程序开始运行前的初始化: 在堆栈上分配一个内存空间,并在该内存空间上放置字符串“Wurstbrot” + '\0'。假设,为字符串分配的内存从 ;即堆栈内存状态如下图所示;AAAA:0000

address     value
AAAA:0000   W
AAAA:0001   u
AAAA:0002   r
...
AAAA:0007   o
AAAA:0008   t
AAAA:0009   0 // that's a zero

B) 当程序开始运行时:

第 1 行:创建指针变量。此变量位于堆栈上,未初始化。对于 32 位系统,此变量位于堆栈上(例如,at address to 并包含一些垃圾值,例如指向某个随机内存。AAAA:0020AAAA:0023DBAC:5782

address     value
AAAA:0020   DB
AAAA:0021   AC
AAAA:0022   57
AAAA:0023   82

第 2 行: 操作系统分配一个长度为 15 字节的内存空间(可能在堆上),并将起始值传递给程序(假设它从 开始)。此值将分配给指针变量,并且第 1 行上的指针值将更改为 。DDDD:0000DDDD:0000

address     value
AAAA:0020   DD
AAAA:0021   DD
AAAA:0022   00
AAAA:0023   00

第 3 行:该行将指针的值重置为指向在步骤 (A) 中分配的内存。从现在开始,指针变量不再指向堆上分配的内存空间,而是指向堆栈上初始化的内存空间。test = "Wurstbrot";test

address     value
AAAA:0020   AA
AAAA:0021   AA
AAAA:0022   00
AAAA:0023   00

第 4 行:当然,这一行会引起错误。它尝试释放步骤 (A) 中初始化的内存空间,而不是在步骤 (B)/1 中分配的内存空间。

解决方案

第 3 行应为:strcpy(test, "Wurstbrot");