千家信息网

c#代码Bug怎么解决

发表于:2025-02-05 作者:千家信息网编辑
千家信息网最后更新 2025年02月05日,本篇内容介绍了"c#代码Bug怎么解决"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!BUG记录5--
千家信息网最后更新 2025年02月05日c#代码Bug怎么解决

本篇内容介绍了"c#代码Bug怎么解决"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

BUG记录5--数组访问越界,导致软件进入HardFault

这是一个比较常见也比较容易忽略的问题,从学习C语言数组开始,我们就被告知数组的下标从0开始,但是我们在实际的案例应用中,序号一般都是从1开始。在一次实际的应用中,采集板采集通道1-通道6的数值,主控板也对应的定义了一个大小为6的数据缓冲区,index从0到5,采集板采集完六个通道的数据,将数据按照帧首、通道号、采样值、帧尾的格式进行打包,然后发送给主控板,主控则对应的根据通道号将采样值存储到缓冲区,因为疏忽编码时采集板的通道号是从1到6写入数据帧的,所以当主控板接收到通道号为6的数据帧就出现了数组越界存储了,此时软件就进入HardFault死循环里面了。

void HardFault_Handler(void){  /* Go to infinite loop when Hard Fault exception occurs */  while (1)  {  }}
BUG记录6--左右移运算符<<、>>和按位与或运算符&、|的优先级问题
//Righthost_control_slave[2] = (gRtcDate&0xFF0000) >> 16;host_control_slave[3] = (gRtcDate&0xFF00) >> 8;host_control_slave[4] =  gRtcDate & 0xFF;//Errorhost_control_slave[2] = gRtcDate & 0xFF0000 >> 16;host_control_slave[3] = gRtcDate & 0xFF00 >> 8;host_control_slave[4] =  gRtcDate & 0xFF;

左右移运算符和按位与或运算符的结合性都是自左向右,前者的优先级高于后者,所以上面两段代码块会得出不同的结果,后面一段代码会先进行右移运算,再进行按位与的运算。我比较懒,一般不怎么去记优先级顺序表,一般都是用()来框起来,这样也有一定的弊端,就是太多括弧看起来也很费劲,所以还是建议常用的一些运算符优先级顺序还是要记一下。

BUG记录7--GPIO模式的配置问题
void GpioConfigInit(void){ GPIO_InitTypeDef  GPIO_InitStructure;   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);     //设置GPIOC_12为推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //设置GPIOC_13为上拉输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     GPIO_Init(GPIOC, &GPIO_InitStructure);           }

在实际的嵌入式项目中,操作GPIO是比较普遍的,但是也隐藏了一些潜在的坑,上面的初始化函数在配置完GPIOC_12和GPIO_13之后,GPIOC_12的推挽输出其实是没有配置成功的,因为此函数中在最后进行了一次结构体初始化的操作,相当于只是把GPIOC_13的模式写入了结构体参数,所以此时两个IO口的模式均为上拉输入,具体我们来分析下GPIO这个结构体的成员参数:

/**   * @brief  GPIO Init structure definition    */typedef struct{   uint16_t GPIO_Pin;             /*!< Specifies the GPIO pins to be configured.                                      This parameter can be any value of @ref GPIO_pins_define */  GPIOSpeed_TypeDef GPIO_Speed;  /*!< Specifies the speed for the selected pins.                                      This parameter can be a value of @ref GPIOSpeed_TypeDef */  GPIOMode_TypeDef GPIO_Mode;    /*!< Specifies the operating mode for the selected pins.                                      This parameter can be a value of @ref GPIOMode_TypeDef */}GPIO_InitTypeDef;/**  * @brief  Initializes the GPIOx peripheral according to the specified  *         parameters in the GPIO_InitStruct.  * @param  GPIOx: where x can be (A..G) to select the GPIO peripheral.  * @param  GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that  *         contains the configuration information for the specified GPIO peripheral.  * @retval None  */void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct){  uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;  uint32_t tmpreg = 0x00, pinmask = 0x00;  /* Check the parameters */  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));  assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));  assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));    /*---------------------------- GPIO Mode Configuration -----------------------*/  currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);  if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)  {     /* Check the parameters */    assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));    /* Output mode */    currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;  }/*---------------------------- GPIO CRL Configuration ------------------------*/  /* Configure the eight low port pins */  if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)  {    tmpreg = GPIOx->CRL;    for (pinpos = 0x00; pinpos < 0x08; pinpos++)    {      pos = ((uint32_t)0x01) << pinpos;      /* Get the port pins position */      currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;      if (currentpin == pos)      {        pos = pinpos << 2;        /* Clear the corresponding low control register bits */        pinmask = ((uint32_t)0x0F) << pos;        tmpreg &= ~pinmask;        /* Write the mode configuration in the corresponding bits */        tmpreg |= (currentmode << pos);        /* Reset the corresponding ODR bit */        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)        {          GPIOx->BRR = (((uint32_t)0x01) << pinpos);        }        else        {          /* Set the corresponding ODR bit */          if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)          {            GPIOx->BSRR = (((uint32_t)0x01) << pinpos);          }        }      }    }    GPIOx->CRL = tmpreg;  }/*---------------------------- GPIO CRH Configuration ------------------------*/  /* Configure the eight high port pins */  if (GPIO_InitStruct->GPIO_Pin > 0x00FF)  {    tmpreg = GPIOx->CRH;    for (pinpos = 0x00; pinpos < 0x08; pinpos++)    {      pos = (((uint32_t)0x01) << (pinpos + 0x08));      /* Get the port pins position */      currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);      if (currentpin == pos)      {        pos = pinpos << 2;        /* Clear the corresponding high control register bits */        pinmask = ((uint32_t)0x0F) << pos;        tmpreg &= ~pinmask;        /* Write the mode configuration in the corresponding bits */        tmpreg |= (currentmode << pos);        /* Reset the corresponding ODR bit */        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)        {          GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));        }        /* Set the corresponding ODR bit */        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)        {          GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));        }      }    }    GPIOx->CRH = tmpreg;  }}

上述的函数会把GPIO的引脚、速度、模式,写入到相关的寄存器中去,在GpioConfigInit()函数中如果只写入一次引脚、速度、模式等参数,那么只会以最后一次的参数为准,因为这里定义的结构体变量为局部变量,在配置GPIOC_13时又重新被赋值,然后再被写入,所以就会出现GPIOC_12模式配置失败的问题,正确的配置函数为:

void GpioConfigInit(void){ GPIO_InitTypeDef  GPIO_InitStructure;   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);     //设置GPIOC_12为推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure);         //设置GPIOC_13为上拉输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure);           }
BUG记录8--触摸屏刷新频率,并不是越快越好

提高触摸屏的刷新频率主要是为了提高用户体验感,让用户用起来感觉更加流畅,但是也不是越快越好,最好要参考触摸屏厂商提供的推荐刷新频率来设置,如下为某款触摸屏的推荐参数:

MCU不要频繁向串口屏发送数据,否则串口屏的内部缓存区会满,从而导致数据丢失(缓冲区大小:标准型8K,基本型4.7K)
1) 一般情况下,控制MCU向串口屏发送数据的周期大于100ms,就可以避免数据丢失的问题;
2) 如果仍然有数据丢失的问题,请判断串口屏的BUSY引脚,为高时不能发送数据给串口屏。

我之前试过10ms来刷新一些参数,然后发现触摸屏的其他一些操作就非常卡顿,因为触摸屏自带的MCU一直在不断的进入数据接收中断并需要不断的处理,有时候还会出现数据乱码,其原因也就是内部的一级缓冲区产生了溢出。

BUG记录9--指针数组的错误寻址

在编程过程中,我一般将指针数组用来存放字符串信息,如下代码块:

const char *ErrInf[5] = { "光子计数器故障!", "空杯测试故障!", "温控仪通讯故障!", "打印机缺纸!", "过温或欠温!"};

那我们看下这些字符串信息如何在内存中存储:

/*! *  \brief     文本框更新*  \param  screen_id 画面ID*  \param  control_id 控件ID*/void WriteTextValue(uint16 screen_id, uint16 control_id, uint8 *pData, uint16 nDataLen){    BEGIN_CMD();    TX_8(0xB1);    TX_8(0x10);    TX_16(screen_id);    TX_16(control_id);    SendNU8(pData, nDataLen);    END_CMD();}

如果需要更新上面的第一个字符串信息,就该按照如下来调用文本框更新函数:

//RightWriteTextValue(0x01, 0x01, (uint8*)ErrInf[0], strlen(ErrInf[0]));//ErrorWriteTextValue(0x01, 0x01, (uint8*)&ErrInf[0], strlen(ErrInf[0]));

因为第一个字符串存储的首地址为ErrInf[0],而非&ErrInf[0],&ErrInf[0]是ErrInf[0]的地址,这两个地址是有区别的,所以千万不要加取地址符&。

BUG记录10--自减运算符引发的问题
typedef struct{ char  *HybDenName; u8  SetHybDenTemp[2]; u32 SetHybDenTime[2];}HybDenPrgPara_TypeDef;typedef struct{ u8 HybDenRow; u8 HybRow; u8 MulRow; u8 HybDenCol; u8 MulCol;}PrgFlowIndex_TypeDef;HybDenPrgPara_TypeDef HybDenFlowPara[PRG_FLOW_NUM_MAX] = { {"DenHyb01", 0, 0, 0, 0}, {"DenHyb02", 0, 0, 0, 0}, {"DenHyb03", 0, 0, 0, 0}, {"DenHyb04", 0, 0, 0, 0}, {"DenHyb05", 0, 0, 0, 0}, {"DenHyb06", 0, 0, 0, 0}, {"DenHyb07", 0, 0, 0, 0}, {"DenHyb08", 0, 0, 0, 0}, {"DenHyb09", 0, 0, 0, 0}, {"DenHyb10", 0, 0, 0, 0},};PrgFlowIndex_TypeDef       PrgFlowIndex = {0x00, 0x00, 0x00, 0x00, 0x00};//code blockcase LoadPgUp:{    if(0x00 == PrgFlowIndex.HybDenRow)    {     PrgFlowIndex.HybDenRow = PRG_FLOW_NUM_MAX-0x01;    }    else    {     PrgFlowIndex.HybDenRow--;    } //在程序加载界面、运行界面、名称编辑写入新的程序名称 SetTextValue(HybDenLoad, LoadName,       (u8*)HybDenFlowPara[PrgFlowIndex.HybDenRow].HybDenName); SetTextValue(HybDenRun, LoadName, (u8*)HybDenFlowPara[PrgFlowIndex.HybDenRow].HybDenName); SetTextValue(HybDenNameEdit, LoadName, (u8*)HybDenFlowPara[PrgFlowIndex.HybDenRow].HybDenName); break;}

如果将PrgFlowIndex.HybDenRow--放置到if-else之前会引发什么问题?当PrgFlowIndex.HybDenRow等于0时,再自减1,其值就变成了255,下面的SetTextValue()函数在写入结构体数组参数时就会写入到非法的内存中去,也会造成HardFault错误。

"c#代码Bug怎么解决"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

数据 问题 运算 函数 参数 数组 模式 触摸屏 运算符 配置 代码 串口 优先级 地址 字符 字符串 实际 结构 缓冲区 道号 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 万方数据库网官网下载 珠海无限软件开发厂家直销 张家口网络技术调试 西门子电机软件开发待遇怎么样 北京软件开发设施检测中心 新时代网络安全学习 服务器主机重启自动进入bios 中国近期网络安全事故 财富数据库杨冰 数据库导入表格出错 sap和软件开发 web服务器代理到应用服务器 珠海搬家服务软件开发设计 参加校园网络安全大赛心得体会 计算机网络技术工程数学答案 权限服务器session作用 知晓诈骗套路网络安全 数据库 count效率 蜀山区品牌网络技术诚信合作 2u服务器硬盘集中供电 新的网络安全法施行时间 一代网络技术和二代网络技术 护苗 网络安全课全五集 计算机软件开发会议室 水果捞数据库安装 中国送物主题数据库 宝山区互联网软件开发值多少钱 调研舆论宣传和网络安全 如何从万方查数据库 松江区通讯网络技术售后保障
0