CSDN问答——精选问答Vol.9

本文整理了CSDN问答社区的热门问题,涵盖C++内存管理如何避免重复释放、tkinter在类外操作text控件、QT槽函数导致的闪退、html文本滚动显示、python连接多SQL执行、js定时器随机间隔及getch区分大写字母与方向键等问题,提供了详细的解决方案。
摘要由CSDN通过智能技术生成

《精选问答》挑选CSDN问答频道每周最新最热的优质回答,为大家提供可信赖的优质解答,点击查看更多已解决问题

目录

1、C++内存管理 怎么避免内存重复释放?

2、封装为类的tkinter,怎么在类外把信息写到Tkinter的text控件中

3、QT定义槽函数获取QTableview的数据出现闪退

4、html文本如何一个个显示并不断上移

5、python 连接多个sql sql并执行sql 怎样用for或其它循环操作

6、js定时器中的间隔时间能否设置为随机数 

7、如何getch区分大写字母P与方向键下键?


1、C++内存管理 怎么避免内存重复释放?

问题描述:

两个实例的成员变量指向了同一块内存,当我要销毁这两个实例时,同一块的内存被释放了两次。
重复释放内存是个很危险的操作,那我现在该怎么解决这个问题?

我的理想办法是在析构函数那加一条“内存是否为空”的判断,但就一直找不到实现方法。。
还是说这就是C++内存管理的难点,只能通过合理的设计结构来避免?

#include <cstdio>
class Example{
    public:
        int *n;
        Example(int *n):n(n){}
        ~Example(){
            delete n;  // if(n != NULL)并不管用, 有啥其他检查方法吗? 
            n = NULL;
            printf("已释放内存\n");
        }
};
 
int main(){
    int *x = new int(666);
    Example *a = new Example(x);  //... 
    Example *b = new Example(x);  //两个类中的指针指向同一块内存 
    printf("a->n: %p, b->n: %p, x: %d\n", a->n, b->n, *x);
    delete a;
    printf("a->n: %p, b->n: %p, x: %d\n", a->n, b->n, *x);
    delete b;  //对 x 指向的内存进行了二次释放! 
    return 0;
}

运行结果:↓

a->n: 00B12E20, b->n: 00B12E20, x: 666
已释放内存
a->n: 00B12E20, b->n: 00B12E20, x: 11611744
已释放内存

 解决方案——来自@bostonAlen的回答

你这里为空判断无法生效,是因为delete后,n变成0xDDDDDDDD , 自然NULL无法判断

#include <cstdio>
class Example{
    public:
        int *n;
        Example(int *n):n(n){}
        ~Example(){
            if(n != (int *)0xDDDDDDDD)
            {
            delete n;  // if(n != NULL)并不管用, 有啥其他检查方法吗? 
            n = NULL;
            printf("已释放内存\n");
            }
            
        }
};
int main(){
    int *x = new int(666);
    Example *a = new Example(x);  //... 
    Example *b = new Example(x);  //两个类中的指针指向同一块内存 
    printf("a->n: %p, b->n: %p, x: %d\n", a->n, b->n, *x);
    delete a;
    printf("a->n: %p, b->n: %p, x: %d\n", a->n, b->n, *x);
    delete b;  //对 x 指向的内存进行了二次释放! 
    return 0;
}
 

但是这样还是有问题,第二次析构,又无法判断了,还是会对损坏。
最好的还是,不进行地址的指向,仅仅是数据的赋值。

#include <cstdio>
 
class Example{
    public:
        int *n;
        Example(int *n):n(new int()){*n = *n;}
        ~Example(){
            if(n != (int *)0xDDDDDDDD || n!=NULL)
            {
            delete n;  // if(n != NULL)并不管用, 有啥其他检查方法吗? 
            n = NULL;
            printf("已释放内存\n");
            }
        }
};
int main(){
    int *x = new int(666);
    Example *a = new Example(x);  //... 
    Example *b = new Example(x);  //两个类中的指针指向同
STM32使用HAL库实现串口通讯的理论讲解可以简要概括如下: 首先,需要明确的是HAL库是什么,它是ST公司官方提供的用于简化STM32芯片开发的一套库函数集合。它封装了底层的硬件操作,提供了一些高级的API函数,使得开发者能够更方便地进行硬件编程。 在STM32中实现串口通讯,主要涉及到以下几个方面的内容: 1. 引入HAL库:在工程中引入HAL库文件,可以通过下载ST官方提供的开发包得到。引入HAL库后,就可以在代码中使用HAL库提供的函数。 2. 初始化串口:调用HAL库提供的函数,进行串口的初始化设置。包括设置波特率、数据位、停止位、校验位等等。 3. 串口发送数据:通过HAL库提供的发送函数,将要发送的数据写入串口的发送缓冲区,然后等待数据发送完成。 4. 串口接收数据:通过HAL库提供的接收函数,可以判断是否接收到了新的数据,若有新的数据到达,则可以通过读取接收缓冲区的方式获取到数据。 5. 中断处理:为了提高串口通讯的效率,一般会使用中断来处理串口接收数据。在中断中,可以读取接收缓冲区的数据,并进行相应的处理。 总结一下,实现STM32的串口通讯主要是通过引入HAL库,进行初始化设置,然后使用库函数发送和接收数据。另外,还可以采用中断的方式处理接收数据。这样就可以实现STM32与其他设备之间的串口通讯。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值