建立网站的意义,绍兴哪些公司做网站,网站开发项目挣钱吗,免费虚拟主机免费空间1.动态内存函数
为什么存在动态内存分配#xff1f;
int main(){int num 10; //向栈空间申请4个字节int arr[10]; //向栈空间申请了40个字节return 0;
}上述的开辟空间的方式有两个特点#xff1a;
空间开辟大小是固定的。数组在声明的时候#xff0c;必须指定数组的…1.动态内存函数
为什么存在动态内存分配
int main(){int num 10; //向栈空间申请4个字节int arr[10]; //向栈空间申请了40个字节return 0;
}上述的开辟空间的方式有两个特点
空间开辟大小是固定的。数组在声明的时候必须指定数组的长度它所需要的内存在编译时分配。
但是对于空间的需求不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道那数组的编译时开辟空间的方式就不能满足了。这时候就需要动态内存开辟了。
1.1 malloc和free
malloc()是用于在程序执行期间动态分配内存。它的全称是memory allocation意为内存分配。malloc()函数是C标准库的一部分它的声明在stdlib.h头文件中。
函数原型如下
void* malloc(size_t size);在这里size是你想要分配的字节数函数返回一个指向分配的内存块起始地址的指针。malloc()函数的返回类型是void*这意味着返回的指针可以赋值给任何指针类型而无需显式转换。
下面简要解释一下malloc()的工作原理 1.你提供想要分配的字节数malloc()在堆内存中搜索一个足够大的连续内存块来存储这些字节。 2.如果找到了合适的内存块它将其标记为已使用并返回该内存块的起始地址的指针。 3.如果找不到足够大的内存块它将返回一个NULL指针表示内存分配失败。 注意使用malloc()分配的内存需要使用free()函数显式地释放否则会导致内存泄漏。
void free(void* ptr);free()函数接受之前分配的内存块的指针并将其释放使其可供将来的动态分配使用。如果忘记释放之前分配的内存程序每次运行分配代码时都会消耗更多内存最终可能导致内存耗尽。
#include stdio.h
#include stdlib.hint main() {int n 5;int* dynamicArray (int*)malloc(n * sizeof(int));if (dynamicArray NULL) {printf(内存分配失败\n);} else {// 使用分配的内存块for (int i 0; i n; i) {dynamicArray[i] i 1;}// 当不再需要分配的内存时记得释放它free(dynamicArray);dynamicArray NULL }return 0;
}在调用free()函数释放动态分配的内存后将指针dynamicArray设置为NULL是一个良好的习惯但不是必须的。
设置指针为NULL的优点 避免悬挂指针Dangling Pointer如果在释放内存后不将指针设置为NULL该指针将仍然保留先前的地址。如果你在后续代码中继续使用该指针可能会导致悬挂指针即指针指向的内存已经被释放这可能导致程序崩溃或产生难以调试的错误。将指针设置为NULL可以帮助你避免这种情况因为如果尝试使用空指针程序将产生明确的错误空指针解引用。避免重复释放在释放内存后如果将指针设置为NULL你可以通过检查指针是否为NULL来确定是否已经释放了内存。如果你在后续代码中错误地再次调用free()会导致未定义的行为。 如果你在后续代码中小心地避免悬挂指针和重复释放内存那么不设置为NULL也不会导致问题。然而这是一个简单且有助于防范错误的额外保护措施所以建议在释放内存后将指针设置为NULL。
1.2 calloc
calloc()是另一个动态内存分配函数也属于标准C库stdlib.h头文件。与malloc()功能类似但在使用上有一些区别。
calloc()函数的原型如下
void* calloc (size_t num, size_t size);其中num是你想要分配的元素数量size是每个元素的大小以字节为单位。calloc()函数会为num * size字节的内存块分配空间并将该内存块中的所有位初始化为零。
相对于malloc()calloc()的一个优势是它会自动初始化分配的内存这意味着你不需要手动将分配的内存清零。在某些情况下这可能是非常有用的特别是当你需要确保分配的内存一开始就是零值时。
实例
#include stdio.h
#include stdlib.hint main() {int n 5;int* dynamicArray (int*)calloc(n, sizeof(int));if (dynamicArray NULL) {printf(内存分配失败\n);} else {// 使用分配的内存块这里的内存已经被初始化为零for (int i 0; i n; i) {printf(%d , dynamicArray[i]); // 输出: 0 0 0 0 0}// 当不再需要分配的内存时记得释放它free(dynamicArray);}return 0;
}总结 calloc mallocmemset 初始化为0 1.3 realloc
realloc是一个用于重新分配内存块大小的函数。具体而言它可以用于更改之前通过malloc或calloc分配的内存块的大小。
realloc函数的声明如下
void *realloc(void *ptr, size_t size);参数说明
ptr指向之前已分配内存块的指针。如果ptr为NULL则realloc的行为就相当于malloc即分配一个新的内存块。size新的内存块大小以字节为单位。
realloc的工作原理如下
如果ptr为NULL那么realloc的行为就等同于malloc(size)它将分配一个新的大小为size字节的内存块并返回指向该内存块的指针。如果size为0且ptr不为NULL那么realloc的行为就等同于free(ptr)即释放掉之前分配的内存块并返回NULL指针。如果ptr不为NULL且size不为0realloc将尝试重新分配之前分配的内存块。可能发生以下几种情况 如果之前分配的内存块大小大于或等于size则不会分配新的内存块而是简单地返回原始内存块的指针不会改变原内存块的内容。如果之前分配的内存块大小小于sizerealloc会尝试将原始内存块扩展到新的大小。这可能会**在原始内存块后面的可用内存空间进行扩展如果没有足够的连续空间来扩展则realloc可能会在另一个地方重新分配一个新的内存块并将原始内容复制到新的内存块中。**这意味着realloc有可能返回一个新的指针而不是原始指针所以在使用realloc后最好将返回的指针赋值给原来的指针。如果realloc在新的内存块分配失败时将返回NULL并且之前分配的内存块仍然保持未更改。
使用realloc时应该特别注意以下几点
如果realloc返回NULL表示重新分配失败原来的指针仍然有效为避免内存泄漏应该保存原来的指针并根据需要释放之前的内存块。当使用realloc时最好不要直接修改原始指针而是将realloc的结果赋值给原始指针以防止意外的内存问题。
实例
#include stdio.h
#include stdlib.h
int main() {int *p (int *) malloc(40);if (p NULL)return 1;//使用int i 0;for (i 0; i 10; i) {*(p i) i;}for (i 0; i 10; i) {printf(%d , *(p i));}//增加空间// p (int *)realloc(p, 80); //如果开辟失败的话p变成了空指针不能这么写int *ptr (int *) realloc(p, 80);if (ptr ! NULL) {p ptr;ptr NULL;}//当realloc开辟失败的时候返回的也是空指针//使用for (i 10; i 20; i) {*(p i) i;}for (i 10; i 20; i) {printf(%d , *(p i));}//释放free(p);p NULL;return 0;
}//输出结果0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 192.常见的动态内存错误
2.1 对NULL指针的解引用操作
#include stdio.h
#include stdlib.h
int main() {int* p (int*)malloc(20);*p 5; //错误,空指针解引用//为了不对空指针解引用 需要进行判断if (p NULL) {perror(malloc);return 1;}else {*p 5;}free(p);p NULL;return 0;
}2.2 对动态开辟空间的越界访问
#include stdio.h
#include stdlib.h
int main() {int *p (int *) malloc(20);if (p NULL)return 1;int i 0;for (i 0; i 20; i)//越界访问 20个字节 只能访问5个整型{*(p i) i;}free(p);p NULL;return 0;
}2.3 对非动态开辟内存使用free释放
#include stdio.h
#include stdlib.h
int main() {int a 10;int* p a;free(p);// ok?return 0;
}编译器会直接报错
2.4 使用free释放一块动态开辟内存的一部分
#include stdio.h
#include stdlib.h
int main() {int *p (int *) malloc(40);if (p NULL)return 1;int i 0;for (i 0; i 5; i) {*p i;p;}//释放//在释放的时候p指向的不再是动态内存空间的起始位置free(p);// p不再指向动态内存的起始位置p;return 0;
}2.5 对同一块动态内存多次释放
#include stdio.h
#include stdlib.h
int main() {int* p (int*)malloc(40);if (p NULL)return 1;int i 0;for (i 0; i 5; i) {*(p i) i;}//重复freefree(p);p NULL;//如果将p赋值为NULL 就可以在free否则编译器会直接报错free(p);return 0;
}2.6 动态开辟内存忘记释放内存泄漏
#include stdio.h
#include stdlib.h
int *get_memory() {int *p (int *) malloc(40);return p;
}int main() {int *ptr get_memory();//使用//释放 如果不释放 就会导致内存泄漏free(ptr);return 0;
}3.C/C程序的内存开辟 C/C程序内存分配的几个区域 栈区stack在执行函数时函数内局部变量的存储单元都可以在栈上创建函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中效率很高但是分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。堆区heap一般由程序员分配释放 若程序员不释放程序结束时可能由OS回收 。分配方式类似于链表。数据段静态区static存放全局变量、静态数据。程序结束后由系统释放。代码段存放函数体类成员函数和全局函数的二进制代码。 普通的局部变量是在栈区分配空间的栈区的特点是在上面创建的变量出了作用域就销毁。 但是被static修饰的变量存放在数据段静态区数据段的特点是在上面创建的变量直到程序结束才销毁所以生命周期变长。
4.经典笔试题
4.1 题目1
#include stdio.h
#include stdlib.h
void GetMemory(char *p) {p (char *) malloc(100);
}void Test(void) {char *str NULL;GetMemory(str);strcpy(str, hello world);printf(str);
}int main() {Test();return 0;
}请问运行Test 函数会有什么样的结果
运行Test函数会导致未定义行为。
在GetMemory函数中传入的char *p是一个局部变量当在函数内部对其进行修改并不会影响到原始调用函数中的指针。这是因为函数的参数是通过值传递的即函数得到的是实参的副本对参数的修改不会影响原始的实参。
在Test函数中将一个NULL指针str传递给GetMemory函数然后在GetMemory函数中分配了内存并将新的地址赋给p。但这对str并没有影响str仍然是一个NULL指针指向未分配的内存。
接着在Test函数中使用strcpy将字符串拷贝到str指向的内存但是str指向的内存并没有被分配这将导致未定义行为。
为了正确地分配内存并使用指针需要修改GetMemory函数使其返回分配的内存地址并在Test函数中接收返回的指针。另外别忘了在使用完内存后需要使用free函数来释放动态分配的内存。
改写1
#include stdio.h
#include stdlib.h
void GetMemory(char **p) {*p (char *) malloc(100);
}void Test(void) {char *str NULL;GetMemory(str); //传指针的地址strcpy(str, hello world);printf(str);//释放free(str);str NULL;
}int main() {Test();return 0;
}改写2
#include stdio.h
#include stdlib.h
char *GetMemory() {char *p (char *) malloc(100);return p;
}void Test(void) {char *str NULL;str GetMemory(); //接受返回的pstrcpy(str, hello world);printf(str);//释放free(str);str NULL;
}int main() {Test();return 0;
}4.2 题目2
char *GetMemory(void) {char p[] hello world;return p;
}void Test(void) {char *str NULL;str GetMemory();printf(str);
}请问运行Test函数会有什么样的结果
在GetMemory函数中定义了一个局部数组char p[] hello world;然后将该数组的地址返回给调用者。但是一旦GetMemory函数执行完毕其局部变量p数组将被销毁因为它是一个自动存储类别的局部变量。所以返回的指针指向的是已经无效的内存。
在Test函数中你将GetMemory的返回值赋给指针str然后使用printf打印str指向的内容。由于GetMemory返回的是一个无效的指针指向已经被销毁的局部数组printf可能会打印出垃圾值或者程序崩溃或者导致其他不可预测的结果。
这个问题被称为悬挂指针问题因为指针悬挂在指向已经无效的内存位置上。
要解决这个问题可以考虑使用动态内存分配来分配存储字符串的内存并在使用完后记得使用free来释放内存。
修改后的代码示例
#include stdio.h
#include stdlib.h
#include string.hchar *GetMemory(void) {char *p (char *)malloc(strlen(hello world) 1);if (p ! NULL) {strcpy(p, hello world);}return p;
}void Test(void) {char *str NULL;str GetMemory();if (str ! NULL) {printf(%s\n, str);free(str); // 释放内存}
}int main() {Test();return 0;
}4.3 题目3
void GetMemory(char **p, int num) {*p (char *) malloc(num);
}void Test(void) {char *str NULL;GetMemory(str, 100);strcpy(str, hello);printf(str);
}请问运行Test函数会有什么样的结果
没有释放内存导致内存泄漏
修改后的代码实例
void GetMemory(char **p, int num) {*p (char *)malloc(num);
}void Test(void) {char *str NULL;GetMemory(str, 100);if (str ! NULL) {strcpy(str, hello);printf(%s\n, str);free(str); // 释放内存}
}4.4 题目4
void Test(void) {char *str (char *) malloc(100);strcpy(str, hello);free(str);if (str ! NULL) {strcpy(str, world);printf(str);}
}请问运行Test 函数会有什么样的结果
str被提前释放再次访问str会导致野指针行为 文章转载自: http://www.morning.tpnx.cn.gov.cn.tpnx.cn http://www.morning.lqqqh.cn.gov.cn.lqqqh.cn http://www.morning.nzsdr.cn.gov.cn.nzsdr.cn http://www.morning.nsrtvu.com.gov.cn.nsrtvu.com http://www.morning.lrflh.cn.gov.cn.lrflh.cn http://www.morning.lfgql.cn.gov.cn.lfgql.cn http://www.morning.rcmcw.cn.gov.cn.rcmcw.cn http://www.morning.bpncd.cn.gov.cn.bpncd.cn http://www.morning.qfrmy.cn.gov.cn.qfrmy.cn http://www.morning.xqknl.cn.gov.cn.xqknl.cn http://www.morning.mnslh.cn.gov.cn.mnslh.cn http://www.morning.qnyf.cn.gov.cn.qnyf.cn http://www.morning.ywpwq.cn.gov.cn.ywpwq.cn http://www.morning.gqfbl.cn.gov.cn.gqfbl.cn http://www.morning.njqpg.cn.gov.cn.njqpg.cn http://www.morning.gjfym.cn.gov.cn.gjfym.cn http://www.morning.chmcq.cn.gov.cn.chmcq.cn http://www.morning.rzmlc.cn.gov.cn.rzmlc.cn http://www.morning.jyknk.cn.gov.cn.jyknk.cn http://www.morning.sfrw.cn.gov.cn.sfrw.cn http://www.morning.fssjw.cn.gov.cn.fssjw.cn http://www.morning.rpsjh.cn.gov.cn.rpsjh.cn http://www.morning.fzlk.cn.gov.cn.fzlk.cn http://www.morning.gwmjy.cn.gov.cn.gwmjy.cn http://www.morning.pxdgy.cn.gov.cn.pxdgy.cn http://www.morning.gtwtk.cn.gov.cn.gtwtk.cn http://www.morning.rwcw.cn.gov.cn.rwcw.cn http://www.morning.qfwfj.cn.gov.cn.qfwfj.cn http://www.morning.gkjnz.cn.gov.cn.gkjnz.cn http://www.morning.mqfw.cn.gov.cn.mqfw.cn http://www.morning.c7629.cn.gov.cn.c7629.cn http://www.morning.mrpqg.cn.gov.cn.mrpqg.cn http://www.morning.srtw.cn.gov.cn.srtw.cn http://www.morning.bpmdh.cn.gov.cn.bpmdh.cn http://www.morning.qkqgj.cn.gov.cn.qkqgj.cn http://www.morning.jwefry.cn.gov.cn.jwefry.cn http://www.morning.yrbq.cn.gov.cn.yrbq.cn http://www.morning.hwhnx.cn.gov.cn.hwhnx.cn http://www.morning.ckbmz.cn.gov.cn.ckbmz.cn http://www.morning.ppdr.cn.gov.cn.ppdr.cn http://www.morning.gjlxn.cn.gov.cn.gjlxn.cn http://www.morning.rdkqt.cn.gov.cn.rdkqt.cn http://www.morning.gqwpl.cn.gov.cn.gqwpl.cn http://www.morning.drzkk.cn.gov.cn.drzkk.cn http://www.morning.fdmtr.cn.gov.cn.fdmtr.cn http://www.morning.tgwfn.cn.gov.cn.tgwfn.cn http://www.morning.supera.com.cn.gov.cn.supera.com.cn http://www.morning.nxpqw.cn.gov.cn.nxpqw.cn http://www.morning.dtmjn.cn.gov.cn.dtmjn.cn http://www.morning.zlnkq.cn.gov.cn.zlnkq.cn http://www.morning.rzmkl.cn.gov.cn.rzmkl.cn http://www.morning.ktmnq.cn.gov.cn.ktmnq.cn http://www.morning.drgmr.cn.gov.cn.drgmr.cn http://www.morning.wjrtg.cn.gov.cn.wjrtg.cn http://www.morning.mtdfn.cn.gov.cn.mtdfn.cn http://www.morning.nhrkl.cn.gov.cn.nhrkl.cn http://www.morning.gktds.cn.gov.cn.gktds.cn http://www.morning.hhzdj.cn.gov.cn.hhzdj.cn http://www.morning.etsaf.com.gov.cn.etsaf.com http://www.morning.rfhm.cn.gov.cn.rfhm.cn http://www.morning.ksggl.cn.gov.cn.ksggl.cn http://www.morning.yggwn.cn.gov.cn.yggwn.cn http://www.morning.kkwgg.cn.gov.cn.kkwgg.cn http://www.morning.xplng.cn.gov.cn.xplng.cn http://www.morning.srwny.cn.gov.cn.srwny.cn http://www.morning.zdbfl.cn.gov.cn.zdbfl.cn http://www.morning.qmrsf.cn.gov.cn.qmrsf.cn http://www.morning.rgwrl.cn.gov.cn.rgwrl.cn http://www.morning.dpnhs.cn.gov.cn.dpnhs.cn http://www.morning.sqmlw.cn.gov.cn.sqmlw.cn http://www.morning.wqhlj.cn.gov.cn.wqhlj.cn http://www.morning.wrkcw.cn.gov.cn.wrkcw.cn http://www.morning.sthgm.cn.gov.cn.sthgm.cn http://www.morning.twmp.cn.gov.cn.twmp.cn http://www.morning.plwfx.cn.gov.cn.plwfx.cn http://www.morning.yrdn.cn.gov.cn.yrdn.cn http://www.morning.dmthy.cn.gov.cn.dmthy.cn http://www.morning.fstesen.com.gov.cn.fstesen.com http://www.morning.lhxkl.cn.gov.cn.lhxkl.cn http://www.morning.wxwall.com.gov.cn.wxwall.com