C动态内存管理_#define

C动态内存管理_#include_02

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

// #include<vld.h>

// 开辟堆区内存:malloc、calloc、realloc
// 释放:free,不释放则会内存泄漏
// 泄露内存被回收的时候:进程退出时、系统重启

/*
void* malloc(size_t size);
void* 指的是通用地址,只知道地址在哪,而不知道该地址存放什么数据
void* calloc(size_t num, size_t size); 分配内存后初始化为0
void* realloc(void* memblock, size_t size); 在新的地方申请3倍内存后,再用指针指向新的地址,一般和原地址不同
void* free(void* memblock);
*/

void realloc_test(){
int n = 10;

// 内存分配失败返回nullptr
// malloc的时候,会添加头尾信息,头部信息用于指明这次分配了多少内存,尾部信息则用于合成内存碎片
int* arr = (int*)malloc(n * sizeof(int)); // 堆区,很大,G为单位,申请的为连续内存


/*
// 假设arr内存不足
// 1.申请
int* arr_tmp = (int*) malloc(2*n*sizeof(int));
// 2.搬家
for(int i=0; i<n; i++){
arr_tmp[i] = arr1[1];
}
// 3.拆旧房子
free(arr1);
// 4.改地址
arr1 = arr_tmp;
arr_tmp = NULL;
*/

arr = (int*)malloc(n * sizeof(int));
printf("%p\n", arr);
arr = (int*)realloc(arr, 2*n*sizeof(int));
printf("%p\n", arr);
free(arr);
}

// 数组越界破坏尾部,导致free崩溃
void free_test1(){
int n = 10;
// 少用
int* arr = (int*)calloc(n, sizeof(int));
// 破坏尾部
arr[n] = 0;
// free会利用malloc的头尾信息,如果头尾信息被破坏,则free无法正常工作
free(arr);
}

// 指针后移导致free出错
void free_test2(){
int n = 10;
int* arr = (int*) malloc(n*sizeof(int));
for(int i=0; i<n; i++){
*arr = 0;
arr++;
}
//这里的free导致程序崩溃,因为arr3此时已经指到了尾部信息,而free需要用到头部信息,但是编译器无法找到头部信息了
free(arr);
}

// 重复free同一内存导致程序崩溃
void free_test3(){
int n = 10;
int* arr = (int*)malloc(n * sizeof(int));
int* p = arr;
free(arr);
free(p);
}

int main(){
int n = 10;
int a[1024*1024]; // 栈区,大概1M,再大程序会崩溃
printf("栈区内存分配成功!\n");

//free_test2();
return 0;
}

C动态内存管理_数据_03

C动态内存管理_#include_04

int main(){
int n = 5;
int m = 10;
int* p = (int*)malloc(sizeof(int) * n);
if (p == nullptr) {
exit(EXIT_FAILURE);
}
for (int i = 0; i < n; i++) {
p[i] = i;
}
// 重新分配内存,将原空间数据拷贝到新空间,释放原空间
// 当realloc内存分配失败时,返回nullptr
p = (int*)realloc(p, sizeof(int) * m);
if (p == nullptr){
exit(EXIT_FAILURE);
}
free(p); // 将内存空间置为未使用,原有数据也发生改变
p = nullptr; // 释放后一定置空

return 0;
}

C动态内存管理_#include_05


​fd​​​表示​​malloc​​生成的上越界和下越界

下面这种写法不安全:指针p被置空,原有空间无法释放,数据也丢失

p = (int*)realloc(p, sizeof(int) * m);

安全写法:

int* tmp = (int*)realloc(p, sizeof(int) * m);
if (tmp == nullptr) {
exit(EXIT_FAILURE);
}
else {
p = tmp;
}

关于状态转移

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

#define BEGIN 0
#define IN_WORD 1
#define OUT_WORD 2
#define END 4

int get_word_num(const char* str) {
int num = 0;
int state = BEGIN;

if (str == nullptr) {
return 0;
}
for (const char* p = str; *p != '\0'; p++) {
switch (state) {
case BEGIN:
if (isalpha(*p)) {
state = IN_WORD;
}
else {
state = OUT_WORD;
}
break;
case IN_WORD:
if ((!isalpha(*p) && (*p) == '`') || ((!isalpha(*p) && (*p) == '-') || isalpha(*p))) {

}else {
state = OUT_WORD;
num++;
}
break;
case OUT_WORD:
if (isalpha(*p)) {
state = IN_WORD;
}
break;
}
}
if (state == IN_WORD) {
num++;
}
return num;
}

int main(){
const char* str = "my mom`s phone is red";
printf("%d\n", get_word_num(str));
return 0;
}

指针理解

C动态内存管理_#include_06