C语言malloc在函数内使用的问题

时间:2022-09-12 18:48:53
假如我用malloc在一个函数内申请了一块堆,然后返回这个块的地址。
当这个函数结束的时候,这块堆空间会不会在程序运行的时候被再次使用?

malloc是给这块空间作了正在使用的标记
可是函数结束后会释放函数执行过程中产生的垃圾
虽然没有free,那么这块空间是否依然被标记正在使用?

例如
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char * create()
{
  char *tmp;
  tmp=(char *)malloc(100);
  return tmp;
}
int main()
{
  char *p;
  p=create();
  strcpy(p,"hello");
  printf("%s\n",p);
  free(p);
  return 0;
}

34 个解决方案

#1


<高质量C/C++>书中有不能返回堆内存
函数在调用完后,会自动释放,返回堆内存,会出错,它的指向会没有内在空间

#2


new是在堆中分配的内存
函数的调用都是在栈上
二者不同

#3


malloc申请的内存会一直存在,直到用free进行释放或程序结束(正常结束或异常结束)。

#4


存在但是不能用的 有冲突的可能

#5


堆和栈是不一样的, 堆有堆的管理,如果简单的说,可以理解为一个链表管理,管理已分配的和未分配的链表,每次malloc和free都会去维护这个链表。

栈是函数调用来管理的,编译的时候基本上就确定下来的:调用函数时,参数压栈,函数内的局部变量也压栈,函数调用完毕后,这些压栈的数据《必须》出栈,出栈后其占用的内存地址就供别人用了,这样也就是无论如何也不能返回栈内存地址的原因。

#6


free后, 要赋空!free(p); p = NULL;

如果没赋空 p就会变成野指针! p的值是不会变的,仍然是一个地址值,仍然指向那块内存区,只是这块内存区的值变成垃圾了。

#7


引用楼主 ren0065 的回复:
假如我用malloc在一个函数内申请了一块堆,然后返回这个块的地址。
当这个函数结束的时候,这块堆空间会不会在程序运行的时候被再次使用?

malloc是给这块空间作了正在使用的标记
可是函数结束后会释放函数执行过程中产生的垃圾
虽然没有free,那么这块空间是否依然被标记正在使用?


这块空间可以正常使用,直到你free它。
就像你代码里写的那样,没有问题。

#8


引用 7 楼 xy_zhang 的回复:
这块空间可以正常使用,直到你free它。
就像你代码里写的那样,没有问题。

不过程序结束之前,最好把它free掉。LZ可以google一下“内存泄漏”。

#9


你的代码是不会出现问题的。但是这种习惯不好。

“函数结束后会释放函数执行过程中产生的垃圾”这是错误的,C没有垃圾回收。

#10


malloc申请的内存会一直存在,直到用free进行释放或程序结束(正常结束或异常结束)。

#11



#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char * create()
{
  char *tmp;
  tmp=(char *)malloc(100);
  return tmp;
}
int main()
{
  char *p;
  p=create();
  strcpy(p,"hello");
  printf("%s\n",p);
  free(p);
  p="123";
  printf("%s",p);
  return 0;
}  

在free(p),后,我又给P赋值了,且能正常执行,是何原因呢?
free(p),不是已经将内存释放了吗?为什么在执行free(p)后,p依然能使用呢?

#12


free(p)是把p所指向的内存释放。p依然可以再指向其它地方。但注意,free(p)之后,不能立即使用p所指向的内存,否则会引起undefined behavior。

#13


引用 11 楼 yonghumingbuzhidao 的回复:
C/C++ code

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char * create()
{
  char *tmp;
  tmp=(char *)malloc(100);
  return tmp;
}
int main()
{
  char *p;
  p=create();
  strcpy(p,"hello"……


这就是传说中的野指针,访问了非法内存,是很危险的。可能现在不出错,但是等出了问题就死也找不到是这里啦,真是程序员的噩梦~
参考6楼,free后置NULL。

#14


野指针,内存泄露都很可怕的

#15


引用 13 楼 xy_zhang 的回复:
引用 11 楼 yonghumingbuzhidao 的回复:

这就是传说中的野指针,访问了非法内存,是很危险的。可能现在不出错,但是等出了问题就死也找不到是这里啦,真是程序员的噩梦~
参考6楼,free后置NULL。


strcpy也很危险。万一源字符串超过了100个字符,后果不堪设想。定位错误也很困难。所以,不要用strcpy,用strncpy。

#16


内存泄露会一点点榨干内存的..

#17


学习一下啊   没这么高水平

#18


C语言好像没有垃圾回收机制,要自己用free。
还有堆和栈有什么区别呢?

#19


引用 13 楼 xy_zhang 的回复:
strcpy也很危险。万一源字符串超过了100个字符,后果不堪设想。定位错误也很困难。所以,不要用strcpy,……


strncpy要加那个头文件?我这里没法用

#20


在c中malloc和free应该是成对,组合出现的。

#21


在大多数UNIX实现中malloc会单独维护一个内存存,即当free后malloc并不会将内存归还给内核,而是自己保留,以便下次继续分配

函数中的内存在栈中分配,而malloc在堆中申请内存,另外一个函数(有些系统不支持)alloca可以在栈上分配内存,当函数调用结束后自动分配,但如果使用这个函数,会造成程序移植性问题。

由于不同的实现,malloc效率并不一样,尤其是当内存申请后,发现申请的内存不够大,需要更改时,这个时候已经不能局限于语言层面上讨论了

另外,一般的strcpy是不检测内存重叠的,但memcpy检测。

#22


引用 19 楼 bobo364 的回复:
引用 13 楼 xy_zhang 的回复:
strcpy也很危险。万一源字符串超过了100个字符,后果不堪设想。定位错误也很困难。所以,不要用strcpy,……


strncpy要加那个头文件?我这里没法用

<string.h>这是标准库中定义的,不会没法用的。

#23


new是在堆中分配的内存
函数的调用都是在栈上

#24


现在先不讨论strcpy的问题,这个只是试验,我通常或用memcpy
我所说的函数结束后会不会被重复使用,不是说我返回了这个指针后能不能够用
而是说这块空间会不会被不可预料的修改,例如我在以后的程序里接连的使用malloc等分配内存的函数
这块在函数中分配的空间会不会被再次分配别的~~返回给某个新指针??
例如,我这个函数中返回的指针地址:100001指向这个块
以后我再次调用函数,是否会让另外的的指针指向这个块中的某个部分?破坏这个块中的数据?

#25


基本上,库函数是不会破坏你的数据的。也不会把已分配的空间再次分配。除非我们自己写越界了。

#26


然后,假如我这样

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void create(char *tmp)
{
  tmp=(char *)malloc(100);
}
int main()
{
  char *p;
  create(p);
  memcpy(p,"hello",6);
  printf("%s\n",p);
  free(p);
  p=NULL;
  return 0;
}


这样的话,跟最初的代码有没有区别?分配的空间有没有被复用的危险?

#27


= =!似乎这两种方式都一样。。。。。NC了我 

#28


引用 25 楼 jim_king_2000 的回复:
基本上,库函数是不会破坏你的数据的。也不会把已分配的空间再次分配。除非我们自己写越界了。

为什么是基本上??
有可能会破坏数据吗?

#29


越界就会破坏数据。LZ可以google一下“缓冲区溢出攻击”。

#30


引用 26 楼 ren0065 的回复:
然后,假如我这样
C/C++ code

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void create(char *tmp)
{
  tmp=(char *)malloc(100);
}
int main()
{
  char *p;
  create(p);
  memcpy(p,"hello",6);
  prin……

疏忽了,你的程序有很严重的问题。


void create(char *tmp)
{
  tmp=(char *)malloc(100);
}

这个tmp只是个局部变量,修改tmp不会引起实参的变化。因此最好用返回值来传出指针。


char *create(size_t size)
{
  return (char *)malloc(size);
}


或者用指针的指针作为参数。


void create(char **tmp)
{
  *tmp=(char *)malloc(100);
}

char *p;
create(&p);

#31


引用 1 楼 weicaijiang 的回复:
<高质量C/C++>书中有不能返回堆内存
函数在调用完后,会自动释放,返回堆内存,会出错,它的指向会没有内在空间

堆内存不会释放,返回指针可以操作

引用 2 楼 ayw215 的回复:
new是在堆中分配的内存
函数的调用都是在栈上
二者不同

我的意思是内存泄漏之类的问题,关于堆内存会不会被复用的问题。
系统标记了某块堆内存,函数的结束会不会影响这个标记?重复的分配堆空间会不会复用这块堆?

引用 3 楼 gaslinux 的回复:
malloc申请的内存会一直存在,直到用free进行释放或程序结束(正常结束或异常结束)。

同上~~一直存在会不会被复用?

引用 4 楼 wxflul 的回复:
存在但是不能用的 有冲突的可能

不明白什么意思= =!

引用 5 楼 freshui 的回复:
堆和栈是不一样的, 堆有堆的管理,如果简单的说,可以理解为一个链表管理,管理已分配的和未分配的链表,每次malloc和free都会去维护这个链表。
。。。

乃也曲解我的意思了

引用 6 楼 jiabin1223 的回复:
free后, 要赋空!free(p); p = NULL;
如果没赋空 p就会变成野指针! p的值是不会变的,仍然是一个地址值,仍然指向那块内存区,只是这块内存区的值变成垃圾了。

同上。。。

引用 7 楼 xy_zhang 的回复:
这块空间可以正常使用,直到你free它。
就像你代码里写的那样,没有问题。

3Q,很感谢你肯定的回复,我会在看看高级c

引用 9 楼 lyramilk 的回复:
你的代码是不会出现问题的。但是这种习惯不好。

“函数结束后会释放函数执行过程中产生的垃圾”这是错误的,C没有垃圾回收。

我的说法的确不对,随口而出,我所之的垃圾是函数内的临时栈变量~~~= =!

引用 21 楼 kktemp234 的回复:
在大多数UNIX实现中malloc会单独维护一个内存存,即当free后malloc并不会将内存归还给内核,而是自己保留,以便下次继续分配

函数中的内存在栈中分配,而malloc在堆中申请内存,另外一个函数(有些系统不支持)alloca可以在栈上分配内存,当函数调用结束后自动分配,但如果使用这个函数,会造成程序移植性问题。

由于不同的实现,malloc效率并不一样,尤其是当内存申请后,发……

精彩回答~~~
内核标记了堆上的某段内存后,如果在函数中没有free,那么函数结束后会不会对这个标记产生影响呢?
我感觉似乎不会影响= =!希望我的猜测是正确的

引用 30 楼 jim_king_2000 的回复:
引用 26 楼 ren0065 的回复:

然后,假如我这样
C/C++ code

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void create(char *tmp)
{
tmp=(char *)malloc(100);
}
int main()
{
char *p;
create(p);
……

我的第二个例子似乎没有那么严重的问题。。。。我正是传了一个指针作为参数阿= =!

#32


修改指针参数需要指针的指针。

#33


引用 1 楼 weicaijiang 的回复:
<高质量C/C++>书中有不能返回堆内存
函数在调用完后,会自动释放,返回堆内存,会出错,它的指向会没有内在空间
堆跟栈是有区别的

#34


引用 32 楼 jim_king_2000 的回复:
修改指针参数需要指针的指针。

哦。。。是哈。。。疏忽掉了= =!

#1


<高质量C/C++>书中有不能返回堆内存
函数在调用完后,会自动释放,返回堆内存,会出错,它的指向会没有内在空间

#2


new是在堆中分配的内存
函数的调用都是在栈上
二者不同

#3


malloc申请的内存会一直存在,直到用free进行释放或程序结束(正常结束或异常结束)。

#4


存在但是不能用的 有冲突的可能

#5


堆和栈是不一样的, 堆有堆的管理,如果简单的说,可以理解为一个链表管理,管理已分配的和未分配的链表,每次malloc和free都会去维护这个链表。

栈是函数调用来管理的,编译的时候基本上就确定下来的:调用函数时,参数压栈,函数内的局部变量也压栈,函数调用完毕后,这些压栈的数据《必须》出栈,出栈后其占用的内存地址就供别人用了,这样也就是无论如何也不能返回栈内存地址的原因。

#6


free后, 要赋空!free(p); p = NULL;

如果没赋空 p就会变成野指针! p的值是不会变的,仍然是一个地址值,仍然指向那块内存区,只是这块内存区的值变成垃圾了。

#7


引用楼主 ren0065 的回复:
假如我用malloc在一个函数内申请了一块堆,然后返回这个块的地址。
当这个函数结束的时候,这块堆空间会不会在程序运行的时候被再次使用?

malloc是给这块空间作了正在使用的标记
可是函数结束后会释放函数执行过程中产生的垃圾
虽然没有free,那么这块空间是否依然被标记正在使用?


这块空间可以正常使用,直到你free它。
就像你代码里写的那样,没有问题。

#8


引用 7 楼 xy_zhang 的回复:
这块空间可以正常使用,直到你free它。
就像你代码里写的那样,没有问题。

不过程序结束之前,最好把它free掉。LZ可以google一下“内存泄漏”。

#9


你的代码是不会出现问题的。但是这种习惯不好。

“函数结束后会释放函数执行过程中产生的垃圾”这是错误的,C没有垃圾回收。

#10


malloc申请的内存会一直存在,直到用free进行释放或程序结束(正常结束或异常结束)。

#11



#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char * create()
{
  char *tmp;
  tmp=(char *)malloc(100);
  return tmp;
}
int main()
{
  char *p;
  p=create();
  strcpy(p,"hello");
  printf("%s\n",p);
  free(p);
  p="123";
  printf("%s",p);
  return 0;
}  

在free(p),后,我又给P赋值了,且能正常执行,是何原因呢?
free(p),不是已经将内存释放了吗?为什么在执行free(p)后,p依然能使用呢?

#12


free(p)是把p所指向的内存释放。p依然可以再指向其它地方。但注意,free(p)之后,不能立即使用p所指向的内存,否则会引起undefined behavior。

#13


引用 11 楼 yonghumingbuzhidao 的回复:
C/C++ code

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char * create()
{
  char *tmp;
  tmp=(char *)malloc(100);
  return tmp;
}
int main()
{
  char *p;
  p=create();
  strcpy(p,"hello"……


这就是传说中的野指针,访问了非法内存,是很危险的。可能现在不出错,但是等出了问题就死也找不到是这里啦,真是程序员的噩梦~
参考6楼,free后置NULL。

#14


野指针,内存泄露都很可怕的

#15


引用 13 楼 xy_zhang 的回复:
引用 11 楼 yonghumingbuzhidao 的回复:

这就是传说中的野指针,访问了非法内存,是很危险的。可能现在不出错,但是等出了问题就死也找不到是这里啦,真是程序员的噩梦~
参考6楼,free后置NULL。


strcpy也很危险。万一源字符串超过了100个字符,后果不堪设想。定位错误也很困难。所以,不要用strcpy,用strncpy。

#16


内存泄露会一点点榨干内存的..

#17


学习一下啊   没这么高水平

#18


C语言好像没有垃圾回收机制,要自己用free。
还有堆和栈有什么区别呢?

#19


引用 13 楼 xy_zhang 的回复:
strcpy也很危险。万一源字符串超过了100个字符,后果不堪设想。定位错误也很困难。所以,不要用strcpy,……


strncpy要加那个头文件?我这里没法用

#20


在c中malloc和free应该是成对,组合出现的。

#21


在大多数UNIX实现中malloc会单独维护一个内存存,即当free后malloc并不会将内存归还给内核,而是自己保留,以便下次继续分配

函数中的内存在栈中分配,而malloc在堆中申请内存,另外一个函数(有些系统不支持)alloca可以在栈上分配内存,当函数调用结束后自动分配,但如果使用这个函数,会造成程序移植性问题。

由于不同的实现,malloc效率并不一样,尤其是当内存申请后,发现申请的内存不够大,需要更改时,这个时候已经不能局限于语言层面上讨论了

另外,一般的strcpy是不检测内存重叠的,但memcpy检测。

#22


引用 19 楼 bobo364 的回复:
引用 13 楼 xy_zhang 的回复:
strcpy也很危险。万一源字符串超过了100个字符,后果不堪设想。定位错误也很困难。所以,不要用strcpy,……


strncpy要加那个头文件?我这里没法用

<string.h>这是标准库中定义的,不会没法用的。

#23


new是在堆中分配的内存
函数的调用都是在栈上

#24


现在先不讨论strcpy的问题,这个只是试验,我通常或用memcpy
我所说的函数结束后会不会被重复使用,不是说我返回了这个指针后能不能够用
而是说这块空间会不会被不可预料的修改,例如我在以后的程序里接连的使用malloc等分配内存的函数
这块在函数中分配的空间会不会被再次分配别的~~返回给某个新指针??
例如,我这个函数中返回的指针地址:100001指向这个块
以后我再次调用函数,是否会让另外的的指针指向这个块中的某个部分?破坏这个块中的数据?

#25


基本上,库函数是不会破坏你的数据的。也不会把已分配的空间再次分配。除非我们自己写越界了。

#26


然后,假如我这样

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void create(char *tmp)
{
  tmp=(char *)malloc(100);
}
int main()
{
  char *p;
  create(p);
  memcpy(p,"hello",6);
  printf("%s\n",p);
  free(p);
  p=NULL;
  return 0;
}


这样的话,跟最初的代码有没有区别?分配的空间有没有被复用的危险?

#27


= =!似乎这两种方式都一样。。。。。NC了我 

#28


引用 25 楼 jim_king_2000 的回复:
基本上,库函数是不会破坏你的数据的。也不会把已分配的空间再次分配。除非我们自己写越界了。

为什么是基本上??
有可能会破坏数据吗?

#29


越界就会破坏数据。LZ可以google一下“缓冲区溢出攻击”。

#30


引用 26 楼 ren0065 的回复:
然后,假如我这样
C/C++ code

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void create(char *tmp)
{
  tmp=(char *)malloc(100);
}
int main()
{
  char *p;
  create(p);
  memcpy(p,"hello",6);
  prin……

疏忽了,你的程序有很严重的问题。


void create(char *tmp)
{
  tmp=(char *)malloc(100);
}

这个tmp只是个局部变量,修改tmp不会引起实参的变化。因此最好用返回值来传出指针。


char *create(size_t size)
{
  return (char *)malloc(size);
}


或者用指针的指针作为参数。


void create(char **tmp)
{
  *tmp=(char *)malloc(100);
}

char *p;
create(&p);

#31


引用 1 楼 weicaijiang 的回复:
<高质量C/C++>书中有不能返回堆内存
函数在调用完后,会自动释放,返回堆内存,会出错,它的指向会没有内在空间

堆内存不会释放,返回指针可以操作

引用 2 楼 ayw215 的回复:
new是在堆中分配的内存
函数的调用都是在栈上
二者不同

我的意思是内存泄漏之类的问题,关于堆内存会不会被复用的问题。
系统标记了某块堆内存,函数的结束会不会影响这个标记?重复的分配堆空间会不会复用这块堆?

引用 3 楼 gaslinux 的回复:
malloc申请的内存会一直存在,直到用free进行释放或程序结束(正常结束或异常结束)。

同上~~一直存在会不会被复用?

引用 4 楼 wxflul 的回复:
存在但是不能用的 有冲突的可能

不明白什么意思= =!

引用 5 楼 freshui 的回复:
堆和栈是不一样的, 堆有堆的管理,如果简单的说,可以理解为一个链表管理,管理已分配的和未分配的链表,每次malloc和free都会去维护这个链表。
。。。

乃也曲解我的意思了

引用 6 楼 jiabin1223 的回复:
free后, 要赋空!free(p); p = NULL;
如果没赋空 p就会变成野指针! p的值是不会变的,仍然是一个地址值,仍然指向那块内存区,只是这块内存区的值变成垃圾了。

同上。。。

引用 7 楼 xy_zhang 的回复:
这块空间可以正常使用,直到你free它。
就像你代码里写的那样,没有问题。

3Q,很感谢你肯定的回复,我会在看看高级c

引用 9 楼 lyramilk 的回复:
你的代码是不会出现问题的。但是这种习惯不好。

“函数结束后会释放函数执行过程中产生的垃圾”这是错误的,C没有垃圾回收。

我的说法的确不对,随口而出,我所之的垃圾是函数内的临时栈变量~~~= =!

引用 21 楼 kktemp234 的回复:
在大多数UNIX实现中malloc会单独维护一个内存存,即当free后malloc并不会将内存归还给内核,而是自己保留,以便下次继续分配

函数中的内存在栈中分配,而malloc在堆中申请内存,另外一个函数(有些系统不支持)alloca可以在栈上分配内存,当函数调用结束后自动分配,但如果使用这个函数,会造成程序移植性问题。

由于不同的实现,malloc效率并不一样,尤其是当内存申请后,发……

精彩回答~~~
内核标记了堆上的某段内存后,如果在函数中没有free,那么函数结束后会不会对这个标记产生影响呢?
我感觉似乎不会影响= =!希望我的猜测是正确的

引用 30 楼 jim_king_2000 的回复:
引用 26 楼 ren0065 的回复:

然后,假如我这样
C/C++ code

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void create(char *tmp)
{
tmp=(char *)malloc(100);
}
int main()
{
char *p;
create(p);
……

我的第二个例子似乎没有那么严重的问题。。。。我正是传了一个指针作为参数阿= =!

#32


修改指针参数需要指针的指针。

#33


引用 1 楼 weicaijiang 的回复:
<高质量C/C++>书中有不能返回堆内存
函数在调用完后,会自动释放,返回堆内存,会出错,它的指向会没有内在空间
堆跟栈是有区别的

#34


引用 32 楼 jim_king_2000 的回复:
修改指针参数需要指针的指针。

哦。。。是哈。。。疏忽掉了= =!