C语言对同一指针两次调用malloc分配内存会发生什么
C指针与malloc相关问题解析
示例代码
int main() { int array[5] = {2, 5, 3, 10, 9}; int *p = (int*) malloc (sizeof (int)); *p = 5; if (-1) { p = (int *)malloc(sizeof (int)); *p=6; } array[0] = *p; free(p); for (int i = 1; i < 5, i++) array[i] += array[0]; return 0; }
注:这段代码的for循环存在语法笔误,循环条件位置写了逗号表达式
i < 5, i++,实际循环终止条件会以最右侧的i++返回值为准,会导致数组越界访问,正常写法应该把逗号改成分号,即for (int i = 1; i < 5; i++)。
问题解答
- 对同一指针重复调用malloc分配内存会产生什么运行结果?
第一次调用malloc时会在堆上分配对应大小的内存,把这块内存的首地址存在指针p里。如果没有提前free这块内存,就直接把第二次malloc返回的新地址赋值给p,第一次分配的内存会直接丢失地址引用,造成内存泄漏——后续没有任何方式能找到这块内存的地址,也就没法主动释放,只能等程序退出后由操作系统回收。在这段代码里,只要进入if分支执行第二次malloc,第一次分配的int大小堆内存就会泄漏。 - 调用free释放该指针后会出现什么情况?
free函数的入参必须是之前malloc/calloc/realloc返回的合法堆地址,不能传入野指针、已释放的指针地址。在这段代码里,不管有没有执行if分支的二次malloc,p存储的都是合法的malloc返回地址,因此free(p)本身是合法操作,会把p当前指向的堆内存标记为空闲状态,交还给堆管理器复用。
要注意两个点:一是free不会自动把p置为NULL,free之后p就成为野指针,如果这时候再解引用*p读写内存,属于未定义行为,大概率触发段错误,也可能篡改堆管理数据造成隐蔽bug;二是这段代码里free之后操作的是栈上的array数组,没有再访问p指向的内存,因此free操作本身不会触发运行错误,但如果走了if分支,第一次malloc的内存泄漏问题仍然存在。 - 代码中的if(-1)条件何时成立、对应分支何时执行?
C语言的逻辑判断规则是表达式值非0即为真,0即为假,-1是有符号整型的非0值,因此这个判断条件恒成立,只要程序执行到if语句位置,分支内的代码一定会执行,不存在跳过分支的情况。不要误以为只有正整数1代表逻辑真,所有正、负非0值在if判断中都等价于逻辑真。
内容的提问来源于stack exchange,提问作者Lokesh Soni
相关产品推荐
相关产品推荐

