嵌入式开发中的防御性C语言编程

嵌入式产品的可靠性自然与硬件密不可分,但在硬件确定、并且没有第三方测试的前提下,使用防御性编程思想写出的代码,往往具有更高的稳定性。

防御性编程首先需要认清C语言的种种缺陷和陷阱,C语言对于运行时的检查十分弱小,需要程序员谨慎的考虑代码,在必要的时候增加判断;防御性编程的另一个核心思想是假设代码运行在并不可靠的硬件上,外接干扰有可能会打乱程序执行顺序、更改RAM存储数据等等。

1 具有形参的函数,需判断传递来的实参是否合法

程序员可能无意识的传递了错误参数;外界的强干扰可能将传递的参数修改掉,或者使用随机参数意外的调用函数,因此在执行函数主体前,需要先确定实参是否合法。

嵌入式开发中的防御性C语言编程

2 仔细检查函数的返回值

对函数返回的错误码,要进行全面仔细处理,必要时做错误记录。

嵌入式开发中的防御性C语言编程

3 防止指针越界

如果动态计算一个地址时,要保证被计算的地址是合理的并指向某个有意义的地方。特别对于指向一个结构或数组的内部的指针,当指针增加或者改变后仍然指向同一个结构或数组。

4 防止数组越界

数组越界的问题前文已经讲述的很多了,由于C不会对数组进行有效的检测,因此必须在应用中显式的检测数组越界问题。下面的例子可用于中断接收通讯数据。

嵌入式开发中的防御性C语言编程

在使用一些库函数时,同样需要对边界进行检查,比如下面的memset(RecBuf,0,len)函数把RecBuf指指向的内存区的前len个字节用0填充,如果不注意len的长度,就会将数组RecBuf之外的内存区清零:

嵌入式开发中的防御性C语言编程

5 数学算数运算

5.1除法运算,只检测除数为零就可靠吗?

除法运算前,检查除数是否为零几乎已经成为共识,但是仅检查除数是否为零就够了吗?

考虑两个整数相除,对于一个signed long类型变量,它能表示的数值范围为:-2147483648 ~+2147483647,如果让-2147483648/ -1,那么结果应该是+2147483648,但是这个结果已经超出了signedlong所能表示的范围了。所以,在这种情况下,除了要检测除数是否为零外,还要检测除法是否溢出。

 #include <limits.h>
 signed long sl1,sl2,result;
 /*初始化sl1和sl2*/    
 if((sl2==0)||(sl1==LONG_MIN && sl2==-1))
 {
     //处理错误    
 }
 else   
 {
     result = sl1 / sl2;
 }

嵌入式物联网需要学的东西真的非常多,千万不要学错了路线和内容,导致工资要不上去!

无偿分享大家一个资料包,差不多150多G。里面学习内容、面经、项目都比较新也比较全!某鱼上买估计至少要好几十。

点击这里找小助理0元领取:嵌入式物联网学习资料(头条)

嵌入式开发中的防御性C语言编程

嵌入式开发中的防御性C语言编程

5.2检测运算溢出

整数的加减乘运算都有可能发生溢出,在讨论未定义行为时,给出过一个有符号整形加法溢出判断代码,这里再给出一个无符号整形加法溢出判断代码段:

嵌入式开发中的防御性C语言编程

嵌入式硬件一般没有浮点处理器,浮点数运算在嵌入式也比较少见并且溢出判断严重依赖C库支持,这里不讨论。

5.3检测移位

在讨论未定义行为时,提到有符号数右移、移位的数量是负值或者大于操作数的位数都是未定义行为,也提到不对有符号数进行位操作,但要检测移位的数量是否大于操作数的位数。下面给出一个无符号整数左移检测代码段:

unsigned int ui1;
unsigned int ui2;
unsigned int uresult;
/*初始化ui1,ui2*/
if(ui2>=sizeof(unsigned int)*CHAR_BIT)
 {
//处理错误  
 }
else
 {
     uresult=ui1<<ui2;
 }

6 如果有硬件看门狗,则使用它

在其它一切措施都失效的情况下,看门狗可能是最后的防线。它的原理特别简单,但却能大大提高设备的可靠性。如果设备有硬件看门狗,一定要为它编写驱动程序。相关推荐:STM32实例-窗口看门狗实验。

  • 要尽可能早的开启看门狗

这是因为从上电复位结束到开启看门狗的这段时间内,设备有可能被干扰而跳过看门狗初始化程序,导致看门狗失效。尽可能早的开启看门狗,可以降低这种概率;

  • 不要在中断中喂狗,除非有其他联动措施

在中断程序喂狗,由于干扰的存在,程序可能一直处于中断之中,这样会导致看门狗失效。如果在主程序中设置标志位,中断程序喂狗时与这个标志位联合判断,也是允许的;

  • 喂狗间隔跟产品需求有关,并非特定的时间

产品的特性决定了喂狗间隔。对于不涉及安全性、实时性的设备,喂狗间隔比较宽松,但间隔时间不宜过长,否则被用户感知到,是影响用户体验的。对于设计安全性、有实时控制类的设备,原则是尽可能快的复位,否则会造成事故。

克莱门汀号在进行第二阶段的任务时,原本预订要从月球飞行到太空深处的Geographos小行星进行探勘,然而这艘太空探测器在飞向小行星时却由于一个软件缺陷而使其中断运作20分钟,不但未能到达小行星,也因为控制喷嘴燃烧了11分钟使电力供应降低,无法再透过远端控制探测器,最终结束这项任务,但也导致了资源与资金的浪费。

“克莱门汀太空任务失败这件事让我感到十分震惊,它其实可以透过硬件中一款简单的看门狗计时器避免掉这项意外,但由于当时的开发时间相当紧缩,程序设计人员没时间编写程序来启动它,”Ganssle说。

遗憾的是,1998年发射的近地号太空船(NEAR)也遇到了相同的问题。由于编程人员并未采纳建议,因此,当推进器减速器系统故障时,29公斤的储备燃料也随之报销──这同样是一个本来可经由看门狗定时器编程而避免的问题,同时也证明要从其他程序设计人员的错误中学习并不容易。

7关键数据储存多个备份,取数据采用“表决法”

RAM中的数据在受到干扰情况下有可能被改变,对于系统关键数据应该进行保护。关键数据包括全局变量、静态变量以及需要保护的数据区域。备份数据与原数据不应该处于相邻位置,因此不应由编译器默认分配备份数据位置,而应该由程序员指定区域存储。相关文章:单片机中的RAM vs ROM。

可以将RAM分为3个区域,第一个区域保存原码,第二个区域保存反码,第三个区域保存异或码,区域之间预留一定量的“空白”RAM作为隔离。可以使用编译器的“分散加载”机制将变量分别存储在这些区域。需要进行读取时,同时读出3份数据并进行表决,取至少有两个相同的那个值。

假如设备的RAM从0x1000_0000开始,我需要在RAM的0x1000_0000~0x10007FFF内存储原码,在0x1000_9000~0x10009FFF内存储反码,在0x1000_B000~0x1000BFFF内存储0xAA的异或码,编译器的分散加载可以设置为:

 LR_IROM1 0x00000000 0x00080000  {    ; load region size_region
   ER_IROM1 0x00000000 0x00080000  {  ; load address = execution address
    *.o (RESET, +First)
    *(InRoot$$Sections)
    .ANY (+RO)
   }
   RW_IRAM1 0x10000000 0x00008000  {  ;保存原码
    .ANY (+RW +ZI )
   }
   RW_IRAM3 0x10009000 0x00001000{    ;保存反码
    .ANY (MY_BK1)
   }
   RW_IRAM2 0x1000B000 0x00001000  {  ;保存异或码
    .ANY (MY_BK2)
   }
 }

如果一个关键变量需要多处备份,可以按照下面方式定义变量,将三个变量分别指定到三个不连续的RAM区中,并在定义时按照原码、反码、0xAA的异或码进行初始化。

 uint32  plc_pc=0;                                                       //原码  
 __attribute__((section("MY_BK1"))) uint32 plc_pc_not=~0x0;              //反码  
 __attribute__((section("MY_BK2"))) uint32 plc_pc_xor=0x0^0xAAAAAAAA;    //异或码

当需要写这个变量时,这三个位置都要更新;读取变量时,读取三个值做判断,取至少有两个相同的那个值。

为什么选取异或码而不是补码?这是因为MDK的整数是按照补码存储的,正数的补码与原码相同,在这种情况下,原码和补码是一致的,不但起不到冗余作用,反而对可靠性有害。比如存储的一个非零整数区因为干扰,RAM都被清零,由于原码和补码一致,按照3取2的“表决法”,会将干扰值0当做正确的数据。

8 对非易失性存储器进行备份存储

非易失性存储器包括但不限于Flash、EEPROM、铁电。仅仅将写入非易失性存储器中的数据再读出校验是不够的。强干扰情况下可能导致非易失性存储器内的数据错误,在写非易失性存储器的期间系统掉电将导致数据丢失,因干扰导致程序跑飞到写非易失性存储器函数中,将导致数据存储紊乱。相关文章:EEPROM和Flash这样讲,我早就懂了。

一种可靠的办法是将非易失性存储器分成多个区,每个数据都将按照不同的形式写入到这些分区中,需要进行读取时,同时读出多份数据并进行表决,取相同数目较多的那个值。

9 软件锁

对于初始化序列或者有一定先后顺序的函数调用,为了保证调用顺序或者确保每个函数都被调用,我们可以使用环环相扣,实质上这也是一种软件锁。此外对于一些安全关键代码语句(是语句,而不是函数),可以给它们设置软件锁,只有持有特定钥匙的,才可以访问这些关键代码。也可以通俗的理解为,关键安全代码不能按照单一条件执行,要额外的多设置一个标志。

比如,向Flash写一个数据,我们会判断数据是否合法、写入的地址是否合法,计算要写入的扇区。之后调用写Flash子程序,在这个子程序中,判断扇区地址是否合法、数据长度是否合法,之后就要将数据写入Flash。

由于写Flash语句是安全关键代码,所以程序给这些语句上锁:必须具有正确的钥匙才可以写Flash。这样即使是程序跑飞到写Flash子程序,也能大大降低误写的风险。

 /***************************************************************
 * 名称:RamToFlash() 
 * 功能:复制RAM的数据到FLASH,命令代码51。
 * 入口参数:dst        目标地址,即FLASH起始地址。以512字节为分界 
 *           src        源地址,即RAM地址。地址必须字对齐 
 *           no         复制字节个数,为512/1024/4096/8192 
 *           ProgStart  软件锁标志    
 * 出口参数:IAP返回值(paramout缓冲区) CMD_SUCCESS,SRC_ADDR_ERROR,DST_ADDR_ERROR, 
 SRC_ADDR_NOT_MAPPED,DST_ADDR_NOT_MAPPED,COUNT_ERROR,BUSY,未选择扇区 
 ****************************************************************/  
 void  RamToFlash(uint32 dst, uint32 src, uint32 no,uint8 ProgStart)  
 {
     PLC_ASSERT("Sector number",(dst>=0x00040000)&&(dst<=0x0007FFFF));
     PLC_ASSERT("Copy bytes number is 512",(no==512));
     PLC_ASSERT("ProgStart==0xA5",(ProgStart==0xA5));
     paramin[0] = IAP_RAMTOFLASH;       // 设置命令字  
     paramin[1] = dst;                  // 设置参数  
     paramin[2] = src;
     paramin[3] = no;
     paramin[4] = Fcclk/1000;
     if(ProgStart==0xA5)                //只有软件锁标志正确时,才执行关键代码  
     {
         iap_entry(paramin, paramout);  // 调用IAP服务程序                 
         ProgStart=0;
     }
     else  
     {
         paramout[0]=PROG_UNSTART;
     }
 }

该程序段是编程lpc1778内部Flash,其中调用IAP程序的函数iap_entry(paramin, paramout)是关键安全代码,所以在执行该代码前,先判断一个特定设置的安全锁标志ProgStart,只有这个标志符合设定值,才会执行编程Flash操作。如果因为意外程序跑飞到该函数,由于ProgStart标志不正确,是不会对Flash进行编程的。

10 通信

通讯线上的数据误码相对严重,通讯线越长,所处的环境越恶劣,误码会越严重。抛开硬件和环境的作用,我们的软件应能识别错误的通讯数据。对此有一些应用措施:

  • 制定协议时,限制每帧的字节数;

每帧字节数越多,发生误码的可能性就越大,无效的数据也会越多。对此以太网规定每帧数据不大于1500字节,高可靠性的CAN收发器规定每帧数据不得多于8字节,对于RS485,基于RS485链路应用最广泛的Modbus协议一帧数据规定不超过256字节。因此,建议制定内部通讯协议时,使用RS485时规定每帧数据不超过256字节;

  • 使用多种校验

编写程序时应使能奇偶校验,每帧超过16字节的应用,建议至少编写CRC16校验程序。

  • 增加额外判断

1)增加缓冲区溢出判断。这是因为数据接收多是在中断中完成,编译器检测不出缓冲区是否溢出,需要手动检查,在上文介绍数据溢出一节中已经详细说明。

2)增加超时判断。当一帧数据接收到一半,长时间接收不到剩余数据,则认为这帧数据无效,重新开始接收。可选,跟不同的协议有关,但缓冲区溢出判断必须实现。这是因为对于需要帧头判断的协议,上位机可能发送完帧头后突然断电,重启后上位机是从新的帧开始发送的,但是下位机已经接收到了上次未发送完的帧头,所以上位机的这次帧头会被下位机当成正常数据接收。这有可能造成数据长度字段为一个很大的值,填满该长度的缓冲区需要相当多的数据(比如一帧可能1000字节),影响响应时间;另一方面,如果程序没有缓冲区溢出判断,那么缓冲区很可能溢出,后果是灾难性的。

  • 重传机制

如果检测到通讯数据发生了错误,则要有重传机制重新发送出错的帧。

11 开关量输入的检测、确认

开关量容易受到尖脉冲干扰,如果不进行滤除,可能会造成误动作。一般情况下,需要对开关量输入信号进行多次采样,并进行逻辑判断直到确认信号无误为止。

12 开关量输出

开关信号简单的一次输出是不安全的,干扰信号可能会翻转开关量输出的状态。采取重复刷新输出可以有效防止电平的翻转。

13 初始化信息的保存和恢复

微处理器的寄存器值也可能会因外界干扰而改变,外设初始化值需要在寄存器中长期保存,最容易被破坏。由于Flash中的数据相对不易被破坏,可以将初始化信息预先写入Flash,待程序空闲时比较与初始化相关的寄存器值是否被更改,如果发现非法更改则使用Flash中的值进行恢复。

公司目前使用的4.3寸LCD显示屏抗干扰能力一般。如果显示屏与控制器之间的排线距离过长或者对使用该显示屏的设备打静电或者脉冲群,显示屏有可能会花屏或者白屏。

对此,我们可以将初始化显示屏的数据保存在Flash中,程序运行后,每隔一段时间从显示屏的寄存器读出当前值和Flash存储的值相比较,如果发现两者不同,则重新初始化显示屏。下面给出校验源码,仅供参考。

定义数据结构:

嵌入式开发中的防御性C语言编程

定义const修饰的结构体变量,存储LCD部分寄存器的初始值,这个初始值跟具体的应用初始化有关,不一定是表中的数据,通常情况下,这个结构体变量被存储到Flash中。

 /*LCD部分寄存器设置值列表*/  
 lcd_redu_list_struct const lcd_redu_list_str[]=
 {
   {SSD1963_Get_Address_Mode,{0x20}                                   ,1}, /*1*/ 
   {SSD1963_Get_Pll_Mn      ,{0x3b,0x02,0x04}                         ,3}, /*2*/ 
   {SSD1963_Get_Pll_Status  ,{0x04}                                   ,1}, /*3*/ 
   {SSD1963_Get_Lcd_Mode    ,{0x24,0x20,0x01,0xdf,0x01,0x0f,0x00}     ,7}, /*4*/ 
   {SSD1963_Get_Hori_Period ,{0x02,0x0c,0x00,0x2a,0x07,0x00,0x00,0x00},8}, /*5*/ 
   {SSD1963_Get_Vert_Period ,{0x01,0x1d,0x00,0x0b,0x09,0x00,0x00}     ,7}, /*6*/ 
   {SSD1963_Get_Power_Mode  ,{0x1c}                                   ,1}, /*7*/ 
   {SSD1963_Get_Display_Mode,{0x03}                                   ,1}, /*8*/ 
   {SSD1963_Get_Gpio_Conf   ,{0x0F,0x01}                              ,2}, /*9*/ 
   {SSD1963_Get_Lshift_Freq ,{0x00,0xb8}                              ,2}, /*10*/
 };

实现函数如下所示,函数会遍历结构体变量中的每一个命令,以及每一个命令下的初始值,如果有一个不正确,则跳出循环,执行重新初始化和恢复措施。这个函数中的MY_DEBUGF宏是我自己的调试函数,使用串口打印调试信息,在接下来的第五部分将详细叙述。

通过这个函数,我可以长时间监控显示屏的哪些命令、哪些位容易被干扰。程序里使用了一个被妖魔化的关键字:goto。大多数C语言书籍对goto关键字谈之色变,但你应该有自己的判断。在函数内部跳出多重循环,除了goto关键字,又有哪种方法能如此简洁高效!

 /** 
 * lcd 显示冗余 
 * 每隔一段时间调用该程序一次 
 */  
 void lcd_redu(void)  
 {
     uint8_t  tmp[8];
     uint32_t i,j;
     uint32_t lcd_init_flag;
     lcd_init_flag =0;
     for(i=0;i<sizeof(lcd_redu_list_str)/sizeof(lcd_redu_list_str[0]);i+)
     {
LCD_SendCommand(lcd_redu_list_str[i].lcd_command);
uyDelay(10);
for(j=0;j<lcd_redu_list_str[i].lcd_value_num;j++)
         {
tmp[j]=LCD_ReadData();
if(tmp[j]!=lcd_redu_list_str[i].lcd_get_value[j])
             {
lcd_init_flag=0x55;
MY_DEBUGF(MENU_DEBUG,("读lcd寄存器值与预期不符,命令为:0x%x,第%d个参数,
             该参数正确值为:0x%x,实际读出值为:0x%x\n",lcd_redu_list_str[i].lcd_command,j+1,
lcd_redu_list_str[i].lcd_get_value[j],tmp[j]));
goto handle_lcd_init;
             }
         }
     }
handle_lcd_init:
if(lcd_init_flag==0x55)
     {
         //重新初始化LCD
         //一些必要的恢复措施  
     }
 }

14 陷阱

对于8051内核单片机,由于没有相应的硬件支持,可以用纯软件设置软件陷阱,用来拦截一些程序跑飞。对于ARM7或者Cortex-M系列单片机,硬件已经内建了多种异常,软件需要根据硬件异常来编写陷阱程序,用来快速定位甚至恢复错误。

15 阻塞处理

有时候程序员会使用while(!flag);语句阻塞在此等待标志flag改变,比如串口发送时用来等待一字节数据发送完成。这样的代码时存在风险的,如果因为某些原因标志位一直不改变则会造成系统死机。

一个良好冗余的程序是设置一个超时定时器,超过一定时间后,强制程序退出while循环。

2003年8月11日发生的W32.Blaster.Worm蠕虫事件导致全球经济损失高达5亿美元,这个漏洞是利用了Windows分布式组件对象模型的远程过程调用接口中的一个逻辑缺陷:在调用GetMachineName()函数时,循环只设置了一个不充分的结束条件。

原代码简化如下所示:

嵌入式开发中的防御性C语言编程

微软发布的安全补丁MS03-026解决了这个问题,为GetMachineName()函数设置了充分终止条件。一个解决代码简化如下所示(并非微软补丁代码):

 HRESULT GetMachineName( WCHAR *pwszPath,  
 WCHARwszMachineName[MAX_COMPUTTERNAME_LENGTH_FQDN+1])
 {
        WCHAR *pwszServerName = wszMachineName;
        WCHAR *pwszTemp = pwszPath + 2;
        WCHAR *end_addr = pwszServerName +MAX_COMPUTTERNAME_LENGTH_FQDN;
        while ((*pwszTemp != L’\\’ ) && (*pwszTemp != L’\0’)&& (pwszServerName<end_addr))  /*充分终止条件*/  
              *pwszServerName++= *pwszTemp++;
        /*… */  
 }
本文链接:https://www.dzdvip.com/34731.html 版权声明:本文内容均来源于互联网。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 395045033@qq.com,一经查实,本站将立刻删除。
(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022年7月14日 21:44
下一篇 2022年7月14日 22:28

相关推荐

  • 游戏demo是什么意思 游戏demo的含义

    1、游戏demo指的是游戏还没有完全制作完成,游戏厂商先放出的试玩版。 2、游戏demo主要是让玩家先体验一下该游戏大致操作和画面,让玩家在购买游戏前有个大致评估。 3、游戏demo只是游戏中的一部分内容,玩家想要玩到完整版需要等到游戏的正式发售。 游戏demo是什么意思?游戏demo简单来说就是游戏一个初始模板示例,为了提前宣发制造热度,是游戏厂家一种提前给玩家预览游玩的间接方式! 英文demo的意思就是样片,演示,模板,顾名思义游戏demo就是游戏的样片,给玩家消费者看产品怎么样的展示手段。在游戏厂家中,游戏demo一般出现在独立工作室和小游戏公司最为广泛,因为他们没有多大的名气声望,即使发布游戏也很少人去关注。大厂有一定的粉丝量和口碑,基本在游戏立项的时候就开始人人皆知,同时,很多大厂都在开发系列游戏,热度基本是够的,所以大厂很少有提前发布游戏demo。 对比小厂和独立游戏开发者,游戏demo的发布就显得尤为重要。游戏demo在小厂和独立游戏开发者眼里就是一个游戏前瞻演示,在游戏还没有开发完成之前,放出一小部分,给予一些关注者期待,也让他们试玩一下,感受如何,会反馈给开发者,开发者也会斟酌进行必要修改完善玩家期待部分。所以说游戏demo是开发者给予玩家(消费者)的样片,让他们看看满不满意,哪里不满意可以提出来我这边改进,游戏demo是双向互利,互相满足的过程。 游戏demo也是在测试游戏不足,当你的游戏demo很棒的时候,无形之中也是一种宣传方式,玩家之间传播,认可的玩家将是游戏正式发售时的主力军。游戏demo是什么意思?就像你去买房,会去先去看样房,适不适合自己的需求,满不满意,有什么需求提出来,售楼部会帮你去解决和完善房子的不足,当你肯定时就会付费购买。 以上就是对“游戏demo是什么意思?”问题的解释,喜欢的记得关注点赞评论,游贻酋长每日更新最新游戏内容。

    2023年2月5日
    11
  • 法不阿贵绳不挠曲是谁提出的?

    “韩非。“法不阿贵,绳不挠曲”出自《韩非子·有度》,这里的“绳”是指中国传统木匠用来打直线的墨线,“绳不挠曲”原意是说墨线不向弯曲的地方倾斜,如果墨线没有拉直,木匠活也就无法正常进行。” 法不阿贵绳不挠曲是什么样意思 “法不阿贵,绳不挠曲。法之所加,智者弗能辞,勇者弗敢争。刑过不避大臣,赏善不遗匹夫。”这是《韩非子·有度》中的一句话,意思是法律不偏袒有权有势的人,墨线不向弯曲的地方倾斜。这启示我们,治国理政,需要秉持法律这个准绳、用好法治这个方式,使法治成为全社会共同的价值和信仰,坚持法律面前人人平等,对触犯纪法者一视同仁,以此彰显公平正义,推动社会发展进步。 先进的思想、理念和文化发扬光大,需要正直果断之人的贯彻执行。东汉时期的董宣,以不畏权贵、严格执法闻名。据史料记载,董宣在担任洛阳县令时,处理过一起棘手的案件。湖阳公主的奴仆白天公然行凶杀人,因为躲在公主家里,官吏抓不到他。等到湖阳公主外出时,却用这个杀人的奴仆做陪乘。董宣亲自率领衙役在洛阳街头围住湖阳公主的车队,搜出这个犯事的奴仆,历数他的罪行,将其就地正法。光武帝了解详情后,不仅没有处罚他,还封了他“强项令”的头衔。 北宋名臣包拯,也是秉公执法、刚正不阿的典范。在端州任职时,包拯曾经写过一首题为《书端州郡斋壁》的诗:“清心为治本,直道是身谋。秀干终成栋,精钢不作钩。仓充鼠雀喜,草尽兔狐愁。史册有遗训,毋贻来者羞。”他以此诗勉励自己,为官者当谋正直之道、立法治之标,始终恪守清廉、正道直行。人们耳熟能详的“铡美案”故事,既彰显了包拯的公正严明、铁面无私,也反映了世人对公平、正义和法治的崇尚追求。 公正是法治的生命线。从近百年党史看,我们党充分吸纳中国优秀传统文化精华,吸收借鉴马克思主义法治观和治理观,一以贯之坚持法律面前人人平等,以实实在在的行动赢得了党心民心。延安时期,革命功臣黄克功因逼婚不成,枪杀陕北公学女学员,被陕甘宁边区高等法院判处死刑。当时,正值抗战用人之际,毛泽东不顾故旧求情,毅然“挥泪斩马谡”。新中国成立之初,高级干部刘青山、张子善因严重贪污盗窃国家资财,被开除出党、判处死刑。公审大会前,有人提出他们都曾为革命立下过汗马功劳,是否可以从轻处理,给他们一个改过的机会。意见反映到毛泽东那里,毛泽东说:“正因为他们两人的地位高,功劳大,影响大,所以才下决心处决他们。只有处决他们,才可能挽救20个、200…

    2022年8月4日
    89
  • 怎么设置 WordPress 静态链接?

    网站URL静态化一直是SEO最重要的基础,不是说动态的URL不能做做好SEO,而是静态话的URL SEO可以更的去完成。更加容易让搜索引擎抓取和喜爱。当然很多人会去找wordpress的一些插件去静态化页面,其实wordpress自带的固定链接就完全不借助插件来完成URL的静态化。

    2021年5月2日
    91
  • 流朱怎么死的(甄嬛传流朱怎么死的)

    “流朱44集死了。 流朱死亡原因: 甄嬛被禁足于碎玉轩备受欺凌,连外面送来的食物都是馊的,甄嬛因病重晕倒。 流朱为替甄嬛求医,强闯碎玉轩大门,却遭到侍卫阻拦。流朱救主心切,绝望之下扑向侍卫手中的刀刃,血流不止,侍卫不得已向皇帝报告实情。 皇帝闻讯震怒,斥责侍卫失职,下令杖责侍卫首领,将内务府苟总管免职,命温实初速救甄嬛和流朱。流朱终因伤势过重死去。” 莞嫔骤然失宠,薄情的皇帝就因为一件衣服迁怒于曾经宠爱无比的甄嬛。 甄嬛昏倒后,碎玉轩的宫门紧闭,流朱为了出宫去找太医,撞刀而死。可方法有千百种,甄嬛昏倒了,更何况还有崔槿汐这个智囊在,流朱为何非要撞刀自尽引起皇帝注意呢?就不能换个方法么?当时的甄嬛,已经失去了几乎所有,娘家获罪,甄远道被投入大狱,其他人被禁足府内,而宫中的甄嬛,虽说皇帝下令按答应的份例对待甄嬛,但是,送去碎玉轩的饭菜竟然都是馊的。雍正即便下旨,苏培盛也断然不会做这样的事情,能背地里这么落井下石的,只有皇后等人。内务府总管姜中敏被杀,新上任的总管也是皇后的人,碎玉轩,已经在皇后的控制之中。此时的甄嬛,已经是叫天天不应叫地地不灵,甄嬛身体一向孱弱,而此番沉重打击,骤然昏厥更让忠心耿耿的流朱担忧不已。流朱对甄嬛的确是忠心耿耿,她已经别无选择,就算弄伤自己,她只是个小宫女,根本无足轻重。反而她若是真伤了自己,反而可能惹怒皇帝,让皇后有了火上浇油的借口,对甄嬛更加不利,流朱唯有一死,用自己的性命换来甄嬛的生机。流朱流朱,流朱用自己的血,成功引起皇帝的注意,换来了希望。相对于浣碧,流朱要忠心耿耿的多。即便甄嬛更多的优待浣碧,不知真相的流朱也从未抱怨什么,无论何时,她都护着甄嬛,哪怕用自己的性命。 浣碧:都是爹的女儿,就因为我娘是罪臣之女,所以爹不认我,所以我只能成为姐姐的丫鬟,虽然长姐私下里对我不错,可丫鬟终究是丫鬟,浣碧要是能像姐姐那样惹人怜爱,那该多好。流朱:小时候无依无靠,是老爷和小姐收留了我,进甄府时,如果不是小姐,恐怕我早就死了,我虽然是丫鬟,但小姐对我像姐妹一样,流朱这辈子都会服侍小姐,为小姐做任何事。历朝历代都会从民间选大量女子当做宫女,例如明朝,宫中宫女近万人,宫女大多都劳动到死为止。 清朝并不存在妃嫔都可以携带陪嫁侍婢入宫的规制,清朝宫中宫女都从内务府上三旗中选择,这也让民间不用担心自家女儿被选入宫服侍,而清朝宫女若无大的过错,二十五岁就能离宫嫁…

    2022年4月22日
    156
  • 电信宽带套餐价格表2021

    2021中国电信宽带套餐价格表分享给大家,每一年宽带套餐的价格都是在变动的,所以需要大家了解清楚,在办理的时候就会比较清楚。根据不同的速度,价格也是有所区别的,下面为大家带来了中国电信2021年最新套餐一览表,一起来看看吧。 2021电信宽带最新套餐价格表 一:融合宽带套餐 融合129套餐: 宽带:包含200M光纤宽带一年使用时间 手机:手机每月畅享20G国内流量、500分钟国内通话,主卡免费,(副卡10元/月/张,与主卡共享套餐) 融合199套餐: 宽带:包含300M光纤宽带一年使用时间 手机:手机每月畅享60G国内流量、1000分钟国内通话,主卡免费,(副卡10元/月/张,与主卡共享套餐) 融合239套餐: 宽带:包含1000M光纤宽带 手机:手机每月畅享80G国内流量、1200分钟国内通话,主卡免费,(副卡10元/月/张,与主卡共享套餐) 融合99套餐: 宽带:包含100M光纤宽带 手机:手机每月畅享1G国内流量、300分钟国内通话,主卡免费,(副卡10元/月/张,与主卡共享套餐) 二:单宽带套餐 三:企业宽带套餐 中国电信2021年最新资费流量套餐一览表 中国电信资费套餐一览表可以在电信的网上营业厅zhi进行查看。打开中国电信zhuan的网上营业厅,选择需要查看的省份区域进入。点击页面中的资费专业,进入以后就可以逐次看到不同业务的对应资费明细了。 电信的5G套餐最低价格为129元,套餐内含30GB流量以及500分钟语音通话,中bai国电信的5G套餐总共分为7档,129 元/ 169元/ 199元/ 239元/ 299元/ 399元/ 599元。 (一 )套餐方案 (二)资费说明 1、国内接听免费,包含来电显示和189邮箱。 2、电信畅享( 99元)套餐外资费:当月国内使用流量超出后,不满167MB按0.03元/MB收费,超过167MB按5 元/1GB收费。流量超过1GB时,仍按上述原则(即每超出1GB按照5元/1GB收费)收费,以此类推。 3、本套餐流量适用于流量不清零规则。 4、套餐超出资费: ( 1 )国内通话:当月国内通话超出对应套餐档位所包含分钟数后,按国内不高于0.15元/分钟计收,不足1分钟按1分钟计。 (2)国内短/彩信:0.1元/条。 (一)资费说明 1、默认开通4G功能,全国接听免费,含来电显示、189邮箱。 2、套餐超出资费: ( 1 )…

    2021年9月21日
    16
  • 40首抖音神曲大全

    在抖音上,无论是原唱歌曲还是翻唱的歌曲, 几乎每隔一段时间, 就会出现一款爆款BGM, 并掀起阵阵热潮。 不知哪些歌曲 令你印象深刻呢? 我们整理了抖音上40首比较火的歌曲, 让我们一起来重温一下吧! 01 《处处吻》 你小心一吻便颠倒众生 一吻便救一个人 给你拯救的体温 总会再捐给某人 一吻便偷一个心 一吻便杀一个人 一寸吻感一寸金 一秒崎岖的旅行 让半夜情人延续吻别人 让你旧情人又惠顾他人 每晚大概有上亿个人 近日,抖音上伴随着广大网友的各种改编, 杨千嬅的一曲《处处吻》再次火爆, 这首杨千嬅在2004年发行的歌曲, 再次涌入人们的视线, 让大多网友直呼 “因为这首歌迷上了粤语的优雅”。 02 《火红的萨日朗》 草原最美的花 火红的萨日朗 一梦到天涯 遍地是花香 流浪的人儿啊 心上有了她 千里万里也会回头望 不怕原唱,就怕翻唱, 这个版本的音乐一响起, 总是让人控制不住想跳舞。 如若有一天,定当去骑马, 奔驰在苍茫的草原上,欣赏这世间的美景, 尝尽世间美味,看遍世间繁华。 用自己喜欢的方式,带上一台相机。 可以的话,带上你一起。 03 《世间美好与你环环相扣》 我知他乘风破浪去了黑暗一趟 感同身受给你救赎热望 知道你不能还要你感受 让星光加了一点彩虹 当樱花开的纷纷扬扬 当世间美好与你环环相扣 也许现在的你只是一个人生活, 但请一定要相信,这个世界上, 总有一个人穿越人海只为与你相拥。 答应我,在那一天到来之前, 请好好爱自己,认真过好每一天, 因为世间美好总会与你环环相扣。 04 《你笑起来真好看》 你笑起来真好看 像春天的花一样 把所有的烦恼所有的忧愁 统统都吹散 你笑起来真好看 像夏天的阳光 整个世界全部的时光 美得像画卷 这首歌在抖音平台上的播放量高达6500多万, 简直是“超级爆款”。 甜美的童声,加上欢快的音调, 让听到歌曲的人不自觉嘴角上扬, 散去一天的疲惫感。 所以,即使生活不顺, 也要报之以微笑, 因为“你笑起来真好看”。 05 起风了 我曾难自拔于世界之大 也沉溺于其中梦话 不得真假 不做挣扎不惧笑话 我曾将青春翻涌成她 也曾指尖弹出盛夏 心之所动 且就随缘去吧 逆着光行走 任风吹雨打 纵有疾风起,人生不言弃。 外面的世界没有想象中自由, 哪怕历经满身风尘, 也愿你归来仍是少年。 06 《你的答案》 黎明的那道光 会越过黑暗 打破一切恐惧我能…

    2021年8月22日
    70