Linux-(C/C++)动态内存分配malloc以及相关学习

1、C/C++内存分类(引用C++ Primer )(对象在C语言中可以理解为变量)

1.1、静态内存:静态内存用来保存局部static对象、类static数据成员、以及定义在任何函数之外的变量

1.2、栈内存:栈内存用来保存定义在函数内非static对象。(当然包含函数参数开辟的内存)

1.3、动态内存:每个程序还有一个内存池,这部分内存被称作自由空间(free store)或者堆(heap)。程序用堆来存储动态分配的内存(dynamically allocate)的对象,也就是,那些在程序运行时分配的对象。动态对象的生存期由程序来控制,所以,不再使用动态对象时,我们的代码必须显示的销毁它们。

note:分配在静态或栈内存的对象由编译器自动创建和销毁,对于栈对象,仅在其定义的程序块运行时才存在,static对象在使用之前分配,在程序结束时销毁。

2、C/C++内存分配相关函数以及运算符

2.1、C分配内存函数如下:(在Linux下查询得知,使用命令:man  3 malloc  )

<span style="font-size:18px;">
</span>
<span style="font-size:18px;">NAME
       malloc, free, calloc, realloc - Allocate and free dynamic memory
SYNOPSIS
       #include <stdlib.h>

       void *malloc(size_t size);
       void  free(void *ptr);
       void *calloc(size_t nmemb, size_t size);
       void *realloc(void *ptr, size_t size);
</span>

size_t类型:   size_t is
the unsigned integer type of the result of sizeof

size_t can
store the maximum size of a theoretically possible object of any type (including array).

size_t is
commonly used for array indexing and loop counting. Programs that use other types

它是一个与机器相关的unsigned类型,其大小足以保证存储内存中对象的大小(来源百度百科)

malloc函数分配size个字节,分配成功返回指向这块分块内存的指针。分配失败将返回NULL;

calloc跟malloc类似,不同点是calloc分配了nmemb*size个字节。

realloc:重新分配内存,一般用于程序追加内存。将改变ptr指向的内存块字节为size,如果一开始ptr为NULL,

那么这个函数实现类似malloc,否则ptr指向的内容在范围(ptr起点和终点(min(old size,new size))将不会改变,如

果new size 大于old size(ptr之前分配的字节),那么多出的那部分是没有初始化的,所以我要习惯初始化这部分内

存。其它部分也类似malloc。

free:这个函数将释放由malloc、calloc、realloc返回指向的内存指针ptr,否则free(ptr)将是未定义的行为。如果

ptr为空,那么free(ptr),将什么都不做。这告诉我们,free(ptr)之后,请务必ptr=NULL;   若不然,ptr便成了悬空指

针,如果往后没分配内存给ptr又再free(ptr),这时将产生未知的错误。

note:通常使用malloc跟free,因为另外两个函数,一般情况下,其实malloc可取代他们。

举个例子,程序如下(大概流程):

<span style="font-size:18px;">// Code...
char *Ptr = NULL;
Ptr = (char *)malloc(100 * sizeof(char));
if (NULL == Ptr)
{
         打印strerror(errno);  //在Linux打印出错信息
}
gets(Ptr); 

// code...
free(Ptr);
Ptr = NULL;   //好习惯
// code...
</span>

2.2C++分配内存

在C++中,动态内存的管理是通过一堆运算符来完成的.

new:        在动态内存中为对象分配空间并返回一个指向该对象的指针。

delete: 接受一个动态对象的指针,销毁一个对象,并且释放与之关联的内存。(数组:delete []数组名),

note:C跟C++分配内存不要混合使用,比如使用new分配的内存,使用free()释放,要知道delete需要完成系列的析构操作,而free只是简单释放而已。有时候侥幸通过,不能保证别的编译器就能通过。

3、分配内存引起注意的地方(大概)

3.1、申请了内存空间后,必须检查是否分配成功。

3.2、当不需要再使用申请的内存时,记得释放;释放后应该把指向这块内存的指针指向NULL,防止程序后面不小心使用了它。

3.2、这两个函数(malloc、free)应该是配对。如果申请后不释放就是内存泄露;如果无故释放那就是什么也没有做。释放只能一次,如果释放两次及两次以上           会出现错误(释放空指针例外,释放空指针其实也等于啥也没做,所以释放空指针释放多少次都没有问题)。

3.4、虽然malloc()函数的类型是(void *),任何类型的指针都可以转换成(void *),但是最好还是在前面进行强制类型转换,因为这样可以躲过一些编译器的检查。

3.5、C使用自定义函数分配内存一般使用二级指针。

来看一个例子,自定义函数分配内存。

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

char *allocate_p(char * str)
{
	str=(char *)malloc(sizeof(char));
}
int main(void )
{
	char *p;//为了测试不初始化NULL
    allocate_p(p);
    free(p);
    printf("OK");
	return 0;
}
/*
 * 使用gcc编译通过,运行报错
*** glibc detected ***
*** ./test1: free(): invalid pointer: 0xb771bff4 ***
*** 说明p是一个悬空的指针,那么allocate_p()没分配空间。
*** 这非常类似值传递,将p没初始化的内存传递给str,函数给str分配内存,
*** 这时p还是原来的那个没初始化内存。当分配函数完了之后,str的动态分配的内存还没释放,
*** p依旧什么都不是。这就导致,该释放的没释放,不该释放的释放了
*** free(p)是未定义的错误
*/

解决方案。

/*
 * 我们是用指针传递来解决值传递不足。
 * 这时候我们也可以利用类似想法来解决这个问题。
 * */
#include<stdio.h>
#include<stdlib.h>

char *allocate_p(char ** str)
{
	*str=(char *)malloc(sizeof(char));
}
int main(void )
{
	char *p;//为了测试不初始化NULL
    allocate_p(&p);
    free(p);
    printf("OK");
	return 0;
}
/*
 * allocate_p(&p);str=p的地址。
 * 那么*str=p。因此
 * *str=(char *)malloc(sizeof(char));
 * 等价于  p==(char *)malloc(sizeof(char));
 * 当free(p) 相当于free(str),注意就不会内存泄漏了
*/

再来看一个经典的例子。

#include <stdio.h>
char *returnStr()
{
    char *p="hello world!";
    return p;
}
int main()
{
    char *str;
     str=returnStr();
    printf("%s/n", str);

    return 0;
}
#include <stdio.h>
char *returnStr()
{
    char p[]="hello world!";
    return p;
}
int main()
{
    char *str;
     str=returnStr();
    printf("%s/n", str);

    return 0;
}
/*
分析:这两个函数唯一差别是returnStr中局部变量*p/p[],
"Hello world"作为静态字符串实际上存储在数据区,但写程序的人不知道这个地址,而程序本身知道。
当某一函数以{ char p[] = "Hello world"; ...}方式使用此静态字符串时,实际上相当于:
  char p[12];
  strcpy(p, "Hello world");
  ....
p[12]是在栈里临时分配的。虽然p指向的内容是"Hello world", 但是这是复制品,不是原件。
当函数结束,char p[]就被程序回收了,所以p[]的内容就不再是"Hello world"了。
但如果以char *p="Hello world"的方式使用,p指向的是静态字符串存储的位置,
也就是说指向"Hello world"的原件,当然没有问题了。
如果想坚持用char p[]而不使用char *p, 有效方法必须是:
char *returnStr()
{
static char p[]="Hello world";
return p;
}
static char []是静态的,存储在数据区。
*/						

参考:http://blog.csdn.net/ssff1/article/details/5006722

时间: 2025-01-06 15:19:22

Linux-(C/C++)动态内存分配malloc以及相关学习的相关文章

C语言中的动态内存分配,malloc/free

malloc函数 原型 extern void *malloc(unsigned int num_bytes); 头文件 #include <stdlib.h> 功能 分配长度为num_bytes字节的内存块 返回值 如果分配成功则返回指向被分配内存的指针(此存储区中的初始值不确定),否则返回空指针NULL.当内存不再使用时,应使用free()函数将内存块释放.函数返回的指针一定要适当对齐,使其可以用于任何数据对象. 说明 关于该函数的原型,在以前malloc返回的是char型指针,新的ANS

String类型_static成员_动态内存分配_拷贝构造函数_const关键字_友元函数与友元类

1:String类型 1 #include <iostream> 2 using namespace std; 3 int main() 4 { 5 //初始化方法 6 string s1 = "hello";//默认构造方法 7 string s2(s1);//将s2初始化为s1的一个副本 8 string s3("value");//将s3初始化为字符串的副本 9 string s4(10,'x');//将字符串初始化为字符x的10个副本 10 co

SQLite剖析之动态内存分配

SQLite通过动态内存分配来获取各种对象(例如数据库连接和SQL预处理语句)所需内存.建立数据库文件的内存Cache.以及保存查询结果.我们做了很多努力来让SQLite的动态内存分配子系统可靠.可预测.健壮并且高效.本文概述SQLite的动态内存分配,软件开发人员在使用SQLite时可以据此获得最佳性能. 1.特性    SQLite内核和它的内存分配子系统提供以下特性:    (1)对内存分配失败的健壮处理.如果一个内存分配请求失败(即malloc()或realloc()返回NULL),SQ

关于c语言内存分配,malloc,free,和段错误,内存泄露

1.   C语言的函数malloc和free (1) 函数malloc和free在头文件<stdlib.h>中的原型及参数        void * malloc(size_t size) 动态配置内存,大小有size决定,返回值成功时为任意类型指针,失败时为NULL. void  free(void *ptr) 释放动态申请的内存空间,调用free()后ptr所指向的内存空间被收回,如果ptr指向未知地方或者指向的空间已被收回,则会发生不可预知的错误,如果ptr为NULL,free不会有任

C++动态内存分配

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解>电子工业出版社等. CSDN视频网址:http://edu.csdn.net/lecturer/144 C / C ++中的动态内存分配是指程序员手动执行内存分配, 动态分配的内存分配给堆,非静态和局部变量获取在Stack上分配的内存.详情查看上篇博文:C程序的内存布局. 什么是应用程序? 动态分配的

【C语言天天练(九)】动态内存分配

引言:数组的元素存储于内存中连续的位置上.当一个数组被声明时.它所须要的内存在编译时就被分配. 可是,我们能够使用动态内存分配在执行时为它分配内存. 一块内存的生命周期能够分为四个阶段:分配.初始化.使用.释放. 内存的分配一般使用C函数库里的malloc函数(原型:void *malloc(size_t size)). 关于malloc函数应该注意一下几点: 1.malloc的參数就是须要分配的内存的字节数. 2.malloc所分配的是一块连续的内存. 3.分配成功.则返回指向分配内存起始地址

28._动态内存分配

动态内存分配 传统数组的缺点(静态内存分配):   1.数组长度必须事先指定,且只能是常整数,不能是变量    例子:     int a[5]; //OK     int len = 5; int a[len]; //error   2.传统形式定义的数组,该数组的内存程序员无法手动编    程释放,在一个函数运行期间,系统为该函数中数组所     分配的空间会一直存在,直到该函数运行完毕时,数组    元素所占存储空间才会被系统释放 3.数组的长度一旦定义,长度就能被改变     4.A函数

Lesson(DynamicMerry)动态内存分配

//  main.m //  1-27随堂笔记 //讲师: 小辉 //笔者: 王学文 //  Created by lanouhn on 15/1/27. //  Copyright (c) 2015年 lanouhn. All rights reserved. //动态内存分配(DynamicMerry) #import <Foundation/Foundation.h> void test() { int x = 10; int y = 20; } //函数返回栈区的数据,是不安全的;一i

动态内存分配函数与释放函数

(1)分配函数 void *malloc(sizeof(unsigned size) 功能:在内存的动态存储区中分配一块长度位size的连续空间. 返回值:指针,存放被分配内存的起始地址.若未申请到空间,则返回NULL(0). void *:指向任何类型的数据,在使用时,要进行强制类型转换. 例如:int *malloc(sizeof(int)) struct student *malloc(sizeof(struct student)) (2)释放函数 void free(void *ptr)