在创建数组的时候,我们必须提前指定数组大小,那就会存在开辟空间过大或者过小的问题,所以需要用到内存管理。
1、malloc
void* malloc(size_t size);
申请一片size字节大小的空间,返回一个指针,这个指针指向的是这片内存空间的起始位置,如果没有申请成功就返回NULL。
2、callocvoid* calloc(size_t num,size_t size);
开辟num个元素的空间,每个元素的大小是size字节,并且初始化为0.
如果成功返回开辟空间的起始地址,否者返回NULL
3、reallocvoid* realloc (void* ptr, size_t size);
修改ptr指向的内存空间的大小,当ptr为NULL时返回realloc的功能和malloc一样。
如果成功返回起始位置的地址,如果失败返回NULL。
在realloc重新开辟空间的过程中,有可能在原有空间上接一个空间,也有可能从新开辟一个空间。
使用realloc的时候需要注意,如果空间增容不成功会返回NULL,会把原来的空间覆盖掉,所以最好不要直接将realloc的返回值赋给原来的指针。
#include
#include
#include
#include
int main()
{
int* str = (int*)malloc(3 * sizeof(int));
if (NULL == str)//开辟不成功
{
printf("%s", strerror(errno));
return 0;
}
int* temp = (int*)realloc(str, 5 * sizeof(int));
if (NULL != temp)
{
str = temp;
temp = NULL;
}
free(str);
str = NULL;
return 0;
}
4、free
将开辟的空间释放掉,free后记得将指针设为NULL
5、常见错误1.对NULL指针的解引用 *** 作
2.对动态开辟空间的越界访问
3.对非动态开辟内存使用free释放
4.使用free释放一块动态开辟内存的一部分(一般情况下不要修改返回指针所指向的位置)
5.对同一块动态内存多次释放
6.动态内存开辟的空间忘记释放(内存泄漏)
6、经典笔试题1.
#include
#include
#include
void GetMemory(char* p)
{
p = (char*)malloc(100);
}
void test()
{
char* str = NULL;
GetMemory(str);
strcpy(str, "hello,world");
printf(str);
}
int main()
{
test();
return 0;
}
1.p没有释放会造成内存泄漏
2.p是str的临时拷贝,因此对p的修改不会影响到str,所以str仍是NULL,对空指针使用strcpy函数会时程序崩溃。
如果想达到预期的效果可以传地址
#include
#include
#include
void GetMemory(char** p)
{
*p = (char*)malloc(100);
}
void test()
{
char* str = NULL;
GetMemory(&str);
strcpy(str, "hello,world");
printf(str);
free(str);
}
int main()
{
test();
return 0;
}
2.
#include
char* GetMemory()
{
char p[] = "hello world";
return p;
}
void test()
{
char* str = NULL;
str = GetMemory();
printf(str);
}
int main()
{
test();
return 0;
}
在GetMemory函数中创建了字符数组p,返回的是字符数组首元素的地址,但是内存空间已经被 *** 作系统释放了,因此通过str去访问那片空间读到的是不确定的值
3.
#include
#include
#include
void test()
{
char* str = (char*)malloc(100);
strcpy(str, "hello");
free(str);
if (str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
int main()
{
test();
return 0;
}
str已经释放了,但是没有置空,会造成非法访问
7、c/c++程序的内存开辟 8、柔性数组在c99中,结构体中的最后一个元素允许是未知大小的数组,这叫做柔性数组成员
struct s
{
int i;
int a[];
};
//或者
struct s
{
int i;
int a[0];
};
柔性数组的特点:
结构中的柔性数组成员前面必须至少一个其他成员。
sizeof返回的这种结构大小不包括柔性数组的内存
包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
#include
#include
struct s
{
int i;
int a[];
};
int main()
{
struct s* ps = (struct s*)malloc(sizeof(struct s) + 40);//int a[10]
return 0;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)