C语言 malloc()函数 分配内存空间尺寸的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言 malloc()函数 分配内存空间尺寸的问题相关的知识,希望对你有一定的参考价值。

char *c = (char*)malloc(0);
scanf("%s",c);
printf("%s",c);

---------------------------------

input:
1234567

output:
1234567
----------------------------------
我只申请了尺寸为0的内存空间,却写入了7个字符,是不是已经修改到了不该修改的内存

应该怎样合理使用malloc()函数?
感谢各位的耐心解答,谢谢!

这个问题首先得从堆栈说起,一个程序一般分为三段:代码段,数据段(静态数据),和堆栈段。堆栈段存储程序中的变量、程序传递的参数等(动态分配的变量存储在堆中,静态分配的存储在栈中)。堆栈的增长方式如下:

程序在运行的时候会预先分配堆栈空间,所以你的问题中不一定修改了不该修改的地方,有可能那里本来就是空的。


再回到malloc这个函数上来,malloc主要负责分配空间,返回该空间的首地址。那为什么申请空间为0,却可以存储7个字符呢?那是因为C语言的指针中并不检查数组的越界问题,不信的话,你可以这样:char ch[5],然后你去读写ch[6](printf或scanf),这样是不会报错的。但是我们在使用的时候,千万别越界使用,因为这样的程序是非常危险的,试想,如果越界使用的地址正好是一个操作系统的地址,那么你一修改,系统就崩了。同时,C语言的这个机制被黑客广泛地应用与缓冲区溢出攻击,所以你非但不能越界使用指针,还得时刻考虑到指针(数组)是否越界,以加强程序的安全性。


希望对你有所帮助。。。

追问

一般怎么来防止越界的问题呢?比如我这里使用 scanf()函数,写代码的时候我不知道运行的时候用户会输入多少字符..
感谢用心~

追答

这个比较简单的方法就是用一个缓冲数组,然后对这个数组进行检测。这个在安全编程中经常用,但是程序效率会有所降低。
比如:char str[100],tmpstr[100]。然后输入到tmpstr中,经检测是否越界后,再赋值给str,这样就可以避免直接使用地址,在对str读写时不会出错。
当然,话又说回来,在刚学习的阶段不用考虑这些问题,否则程序的复杂程度会大大增加,不利于学习,但是在做项目时要有这个意识。

参考技术A C语言中malloc是动态内存分配函数。
函数原型:void *malloc(unsigned int num_bytes);
参数:num_bytes 是无符号整型,用于表示分配的字节数。
返回值:如果分配成功则返回指向被分配内存的指针(此存储区中的初始值不确定),否则返回空指针NULL。void* 表示未确定类型的指针,void *可以指向任何类型的数据,更明确的说是指申请内存空间时还不知道用户是用这段空间来存储什么类型的数据(比如是char还是int或者...)
功能:分配长度为num_bytes字节的内存块
注意:当内存不再使用时,应使用free()函数将内存块释放。函数返回的指针一定要适当对齐,使其可以用于任何数据对象。关于该函数的原型,在以前malloc返回的是char型指针,新的ANSIC标准规定,该函数返回为void型指针,因此必要时要进行类型转换。
实例:
#include"stdio.h"

#include"malloc.h"//malloc()函数被包含在malloc.h里面

int main(void)


char*a=NULL;//声明一个指向a的char*类型的指针

a=(char*)malloc(100*sizeof(char));//使用malloc分配内存的首地址,然后赋值给a

if(!a)//如果malloc失败,可以得到一些log


perror("malloc");
return-1;


sprintf(a,"%s","HelloWorld\n");//"HelloWorld\n"写入a指向的地址

printf("%s\n",a);//输出用户输入的数据

free(a);//释放掉使用的内存地址

return0;

参考技术B malloc是给指针变量分配内存空间的函数命令
正确使用:
分配的空间要能保证容下你想存储的数据,不要和机器逗着玩(分配0空间,或少于自己实际需要的空间),如你上面的操作,表面上你程序运行没有问题,可实际上你占用了别人的地盘,只是当前你很幸运没有使程序出现问题,但不保证一定不出问题!!

不再使用的指针,一定要free()来释放空间!malloc 与free要配对使用,即:有malloc必要有free追问

可是... 使用scanf(),我怎么能知道程序运行的时候,用户会输入多少字符?那这时应该怎样确定分配多大内存?

追答

这个在应用程序设计时会限制用户输入的有效数据的长度的!
在真正的程序设计时,我们很少会用scanf()函数来进行数据输入,会采用相应的有效代码(因开发系统情况而异) malloc函数只是动态分配内存的一个命令,学者只需要知道它的用法就好了,具体情况要具体分析进而确定程序实现方式。

本回答被提问者和网友采纳
参考技术C

你何必纠结一定要分配用户输入字符数量长度的空间呢?开一个足够大的数组不就得了?

如果你一定要malloc准确的大小,你可以

char *c;
char *s=malloc(100000*sizeof(char));//malloc一个足够大的数组,暂时储存输入
scanf("%s",s);
c=(char*)malloc(strlen(s)*sizeof(char));
strcpy(c,s);
free(s);//输入结束后把输入储存,再把这个大数组释放

怎么查看动态分配内存空间的大小(c语言)。

用malloc函数分配的内存空间大小用什么函数能显示出来大小。比如sizeof(int)可显示int空间的大小,p=(int *)malloc(10000)怎么显示出来10000的空间大小

1、这个空间是自己分配的,既然已经写了p=(int *)malloc(10000)那就分配10000的大小,还需要显示多少大小。对于一个指向一块内存的指针如果用比如sizeof(p)显示大小(int * p=new int[10]),也只是显示4,代表首地址大小,不能显示正块内存的大小,而且根本没有意义。
2、动态内存分配,可以自由的分配指定大小的内存空间。当程序运行时,程序员并不清楚某一数据需要的具体内存空间大小时,可以使用动态分配。
  malloc函数原型
  void *malloc(int nSize)
  分配一个nSize大小的内存空间,如果分配成功则返回地址空间的首地址,如果分配失败则返货NULL
  nSize一般使用 sizeof(类型A)*N 的计算方式获取大小。意思为:为分配n个类型A所占空间的大小。
  获取的指针地址需要强制转换为指定类型
例如:int *p = (int*)malloc(sizeof(int)*100);
  使用malloc动态分配的内存空间需要使用free函数手动释放。
参考技术A 在c语言中,要在堆上分配空间,需要使用内存申请函数。一般用malloc。
void
*
malloc(int
size);
可以申请一段长度为size字节的空间,并返回空间的首地址。
要清空分配的内存空间,也就是将该空间所有字节均赋值为0,可以使用memset函数。
该函数声明与string.h中,形式为
void
memset(void
*start,
int
value,
int
size);
如果要清空空间的首地址为p,大小为len,则可以调用
memset(p,
0,
len);
参考技术B 这个空间是你自己分配的,既然已经写了p=(int *)malloc(10000)那就给你分配10000的大小,还需要显示多少大小?
对于一个指向一块内存的指针如果用比如sizeof(p)显示大小(int * p=new int[10]),也只是显示4,代表首地址大小,不能显示正块内存的大小,而且根本没有意义,不就是10吗本回答被提问者采纳
参考技术C 自己malloc出来当然知道字节大小,如果把指针传给一个函数呢,函数如果不知道其空间大小,对其操作时是有很大溢出风险的,但我又不想增加一个传入参数,sizeof()的确算不出指针指向的空间大小,那只能将指针交给与他人使用的时候,把空间大小也告诉对方。所以有时候没办法要妥协一下
只通过指针貌似无法知道指针指向的空间大小,那么free函数又是怎么知道呢。malloc在分配空间的时候会多分配一些空间来存放分配信息。(据说在每个内存块的最前的4个字节就存放了malloc的字节大小信息,可以自己写一个函数把这些数据提出来,我目前还没有试验过)

以上是关于C语言 malloc()函数 分配内存空间尺寸的问题的主要内容,如果未能解决你的问题,请参考以下文章

c语言中malloc是啥?怎么用?

怎么查看动态分配内存空间的大小(c语言)。

c语言中啥是动态分配内存?

C语言动态数据结构

C语言中的malloc函数的使用?

内存分配函数(C语言)