1.良好的实践是始终结合使用 memset 和 malloc,或者使用 calloc.
char *p = malloc (10);
memset(p,’\0’,10);
2.由于 p 已被分配了 10 个字节,如果某个代码片段尝试向 p 写入一个 11 字节的值,则该操作将在不告诉您的情况下自动从其他某个位置“吃掉”一个字节
char *name = (char *) malloc(11);
// Assign some value to name
memcpy ( p,name,11); // Problem begins here
作为良好的实践,每当向指针写入值时,都要确保对可用字节数和所写入的字节数进行交叉核对。一般情况下,memcpy 函数将是用于此目的的检查点
3.内存读取越界
char *ptr = (char *)malloc(10);
char name[20] ;
memcpy ( name,ptr,20); // Problem begins here
在本例中,memcpy 操作尝试从 ptr 读取 20 个字节,但是后者仅被分配了 10 个字节.这还会导致不希望的输出.
4.内存泄漏
1)char *memoryArea = malloc(10); ---> 区域1
char *newArea = malloc(10); ---> 区域2
memoryArea = newArea; ---如果某人执行如下所示的语句(指针重新赋值)……则它肯定会在该模块开发的后续阶段给您带来麻烦。
因为,memoryArea 以前所指向的内存位置变成了孤立的,
2)如果指针的指针,先遍历并释放子内存位置,然后再释放父内存位置
free( memoryArea->newArea);
free(memoryArea);
3)返回值的不正确处理
有时,某些函数会返回对动态分配的内存的引用。跟踪该内存位置并正确地处理它就成为了 calling 函数的职责。
char *func ( )
{
return malloc(20); // make sure to memset this location to ‘\0’…
}
void callingFunc ( )
{
func ( ); // Problem lies here
}
5.归还内存
在开发组件时,可能存在大量的动态内存分配。您可能会忘了跟踪所有指针(指向这些内存位置),并且某些内存段没有释放,还保持分配给该程序。
始终要跟踪所有内存分配,并在任何适当的时候释放它们。事实上,可以开发某种机制来跟踪这些分配,比如在链表节点本身中保留一个计数器(但您还必须考虑该机制的额外开销)
6.访问空指针
访问空指针是非常危险的,因为它可能使您的程序崩溃。始终要确保您不是 在访问空指针
7.注意&&总结:(要避免内存相关的问题,良好的实践是)
1)始终结合使用 memset 和 malloc,或始终使用 calloc。
2)每当向指针写入值时,都要确保对可用字节数和所写入的字节数进行交叉核对。
3)在对指针赋值前,要确保没有内存位置会变为孤立的。
4)每当释放结构化的元素(而该元素又包含指向动态分配的内存位置的指针)时,都应首先遍历子内存位置并从那里开始释放,然后再遍历回父节点。
5)始终正确处理返回动态分配的内存引用的函数返回值。
6)每个 malloc 都要有一个对应的 free。
7)确保您不是在访问空指针。
阅读(1745) | 评论(0) | 转发(0) |