你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

C语言内存操作的那些坑?

[复制链接]
gaosmile 发布时间:2020-9-22 12:24
1、返回局部变量的地址,或者返回指向局部变量的指针

int *stackref()
{
    int val;
    return &val;
}
2、引用已经被释放了的堆内存(野指针)
int * heapref(int n, int m)
{
    int i;
    int *x, *y;
    x = (int *)malloc(n * sizeof(int));
    /*  各种操作 */
    free(x);
    x = NULL;

    y = (int *)malloc(m * sizeof(int));
    for(i = 0; i < m; i++) {
        y = x++;  // 此处的x之前已经被释放了!
    }
}
3、内存泄漏
malloc和free没有配套使用 void leak(int n)
{
     int *x = (int *)malloc(n * sizeof(int));
     return;
}
或者:
char *p = (char *)malloc(10);
p = (char *)malloc(10);

结构体资源释放常见内存泄漏问题

struct a{
    int buf_size;
    char *buf;
};
struct a *p = (struct *a)malloc(sizeof(struct a));
  • 忘记给成员buf分配空间就使用
  • 释放的时候,忘记释放buf
  • 先释放了p,再释放buf

free(p);
free(p->buf);

多步骤内存初始化

char *buf1;
char *buf2;
int module_init()
{
    buf1 = (char *)malloc(100);
    if(buf1 == NULL)
        return -1;

    buf2 = (char *)malloc(100);
    if(buf2 == NULL)
       return -1;//执行到这里,buf1内存泄漏

    free(buf2);
    free(buf1);
    ...  
}
解决对策是对出错处理修改成goto语句,而非直接return。

调用了会分配内存的函数,使用完未做内存回收处理。
实际开发最常见,常常是调用会分配内存的第三方函数库。
char *func ( )
{
    return (char *)malloc(20); // make sure to memset this location to ‘\0’…
}

void callingFunc ( )
{
    char * p = func ( ); // Problem lies here
    ...
}
4、栈越界
{
    char buf[5];
    sprintf(buf, "%s", "hello world");
}
上面的代码导致栈缓冲区溢出,安全的做法是:
1)根据需求定义合适的buffer;
2)采用snprintf(buf, sizeof(buf), "%s", "hello world")来及时截断。
5、误认为从堆分配的内存被初始化为0
int *p = malloc(24 * sizeof(int));

char a[] = “abcdefghiafa”;
int i = 0;
while(a != '\0')
{
    i++;
    p[*a - 'a']++;
}
6、引用未初始化的指针,或者访问NULL指针
int *p;
int a = *p;
7、间接访问无效地址,类似于引用未初始化的指针
如从stdin读取一个int变量时,scanf("%d", &val);是正确用法,若误写为scanf("%d", val);时,val的值会被解释为一个地址,并试图向该地址写数据。在最好的情况下,进程立即异常中止。在最坏的情况下,val的值恰好对应于虚拟存储器的某个合法的具有读/写权限的内存区域,于是该内存单元会被改写,而这通常会在相当长的一段时间后造成灾难性的、令人困惑的后果。
8、堆越界
char *p = (char *)malloc(10);
char *q = (char *)malloc(10);
char a[20] = "abcdefghijklmno"
memcpy(p,a,sizeof(a));//可能无意中修改了q指针指向的堆数据
9、谨慎使用strcpy,memcpy等拷贝函数,字符串数组赋值之前或者定义之后最好memset一下
char p[10];
strcpy(p,"hello world!");//数组越界

strncpy(p,"hello world!",sizeof(p));//不越界,但是少了结尾'\0'

memset(p,'\0',sizeof(p));
strncpy(p,"hello world!",sizeof(p) - 1);//正确
10、使用未初始化的内存
char *p = (char *)malloc(10);
char a[10] = "abcd";
strcpy(a,p);//结果未知
11、当使用malloc来申请内存时,应该用if(p != NULL)进行防错检查。
12、意图通过传递指针来分配内存
void *GetMemory(void *p,int n)
{
    p = malloc(n);
    return p;
}

char *p;
GetMemory((void *)p,10);
*p = 'a';


收藏 评论0 发布时间:2020-9-22 12:24

举报

0个回答

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版