简体   繁体   English

修复内存覆盖错误可能是由于STM32 Nucleo-F334R8上的malloc引起的

[英]Fixing a Memory Overwrite errors likely due to malloc on an STM32 Nucleo-F334R8

I hope this is a clear explanation of my issue I've been runnign around various manuals for a little over a week now tryign to solve this: 我希望这是对我的问题的一个明确的解释我已经围绕各种手册运行了一个多星期,现在尝试解决这个问题:

Recently I have been redesigning a software design for a class project after feedback and testing on the STM32 Nucleo-F334R8(my initial code was riddled with memory and timing errors) 最近,在对STM32 Nucleo-F334R8进行反馈和测试之后,我一直在重新设计一个类项目的软件设计(我的初始代码充满了内存和定时错误)

Currently I run into two main errors: 目前我遇到两个主要错误:

(This issue has been resolved) (此问题已得到解决)

I had been using sprintf not accounting for the trailing null character writting outside of allocated memory. 我一直在使用sprintf而不考虑在分配的内存之外写入的尾随空字符。

When processing USART Data using USART 1 in Asynchronous mode at 115200 Baudrate: 使用USART 1在异步模式下以115200波特率处理USART数据时:

Program received signal SIGTRAP, Trace/breakpoint trap. 程序接收信号SIGTRAP,跟踪/断点陷阱。 0x08002c08 in memset () memset()中的0x08002c08

Program received signal SIGTRAP, Trace/breakpoint trap. 程序接收信号SIGTRAP,跟踪/断点陷阱。 0x08002c08 in memset () memset()中的0x08002c08

Program received signal SIGTRAP, Trace/breakpoint trap. 程序接收信号SIGTRAP,跟踪/断点陷阱。 0x08002c08 in memset () memset()中的0x08002c08

Program received signal SIGTRAP, Trace/breakpoint trap. 程序接收信号SIGTRAP,跟踪/断点陷阱。 0x08002c08 in memset () memset()中的0x08002c08

Program received signal SIGTRAP, Trace/breakpoint trap. 程序接收信号SIGTRAP,跟踪/断点陷阱。 0x080056b4 in std.isra () std.isra中的0x080056b4()

The value stored at the address 0x08002c08 in question is usually very large typically something like 134228385 in decimal. 存储在地址0x08002c08中的值通常非常大,通常为十进制的134228385。 Also if I forcefully step through the issue the program continues to run fine and never encounters the problem again which I find strange possible cause? 此外,如果我强行执行该问题,该程序继续运行正常, 再也没有遇到问题 ,我觉得奇怪的可能原因?

UPDATE: So I've traced the memset issue around a bit and found that it occurs during my setOutputBuffer method: 更新:所以我已经跟踪了memset问题,发现它发生在我的setOutputBuffer方法中:

 String>,%5d,%8s,%3d,%3d,%3d,%4d,%4d,%4d,%10.6f,%11.6f,%7.1f,%3d,%3.1f\\n",uptime,timeString,temperature,pressure,humidity,acc1,acc2,acc3,latitude,longitude,altitude,current,voltage); } ``` Which leads me to believe the issue lies in finding a value that is being used to set the Output buffer message. I would like advice on how to further troubleshoot these two issues and whether there is a chance that the memset error is related the later bss error. My String Tokenizing code(edited): ```c void tokenize(char* in){ const char *p = in; const char delim[] = ","; char *token = NULL; uint8_t n = 0; do{ size_t length = strcspn(p, delim); if(length > 0){ if(token == NULL){ token = malloc(sizeof(char)*length); // create memory space for the token memset(token, 0, length); // ensure initialized memory is blank sprintf(token, "%.*s",(int)length,p); // store the token from a substring of Input Buffer p+=length; // move pointer to next ',' parseToken(token, n); // extract information from the token be it latitude, longitude etc memset(token, 0, length); // clear the token free(token); // free up the token's spot in memory token = NULL; // set token pointer to null n++; } } }while(*((++p)+1) != '*'); // The expected string ends with a checksum character '*' after the last ',' } ``` I've re-examined the function and made a lot of changes now I can successfully step through the entire function without issue, the program then returns to my main loop, and I let it run for a while but then I suddenly run back into the same memset issue, even without receiving any bytes over USART here is the code for my main loop and the subsequent function calls it makes: ```c while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if (byteFlag){ byteRecieved(); byteFlag = 0; } if(msgFlag){ msgRecieved(); msgFlag = 0; } if(secFlag){ setOutputBuffer(); HAL_UART_Transmit(&huart1, (uint8_t *)bufferOut, 91, 1000); secFlag = 0; } } ``` byteReceived: ```c if((char) byteIn == '$'){ clearInputBuffer(); } else if((char) byteIn == '\\n'){ msgFlag = 1; } else{ storeChar(); } ``` msgReceived: ```c if(isValid()){ if (checksum()) { tokenize(bufferIn); clearInputBuffer(); } } ``` isValid: ```c char substr[5]; strncpy(substr, (bufferIn+1), 5); if(!strcmp(substr, "GPGGA")){ return 1; } return 0; ``` checksum: ```c int checksum(){ int calc_checksum = 0; int in_checksum; int i = 0; char checkstr[2]; uint8_t hasCheckSum = 0; for(int j = 0; j<91; j++){ if (bufferIn[j] == '*') { hasCheckSum = 1; i = 1; } } if (hasCheckSum) { while (bufferIn[i] != '*'){ calc_checksum ^= bufferIn[i]; i++; } checkstr[0] = bufferIn[i+1]; checkstr[1] = bufferIn[i+2]; } else {return 0;} in_checksum = parseStr_HexToInt(checkstr); if (calc_checksum == in_checksum){ return 1; } else { return 0; } } ``` clearInputBuffer: ```c void clearInputBuffer(){ int i = 0; for(i = 0; i < 100; i++){ bufferIn[i] = ' '; } bufferIn[0] = '$'; } ``` 

(This issue has been resolved) (此问题已得到解决)

Essentially the source of my problem was misuse of sprintf and overwritting program code with null characters 基本上我的问题的根源是滥用sprintf并用空字符覆盖程序代码

I encountered a breakpoint trap while filling the bss segment of the board's memory 我在填充电路板内存的bss段时遇到了断点陷阱

And after adding Seven GPIO Ports for a 4bit mode LCD(namely PA12, PA11, PB12, PB11, PB2, PB1, PB15) and two for a two channel ADC in DMA mode (PA1, PA0): 为4位模式LCD(即PA12,PA11,PB12,PB11,PB2,PB1,PB15)添加7个GPIO端口后,为DMA模式下的双通道ADC(PA1,PA0)添加2个:

Program received signal SIGTRAP, Trace/breakpoint trap. 程序接收信号SIGTRAP,跟踪/断点陷阱。 LoopFillZerobss () at ..\\startup/startup_stm32f334x8.s:103 103 cmp r2, r3 While trying to implement LCD and ADC functionality I receive the breakpoint trap error during the LoopFillZerobss function of startup which proved fatal , particularly by stopping my USART from reporting at all(however it can still receive bytes as interrupt and process tokens etc, just refuses to transmit), After reading up into the bss segment I attempted to solve the issue by initializing as many global variables as I could to non-zero values, this did not work, the problem is observed after adding the STM32CubeMx settings for ADC and the 7 GPIO pins used in the LCD, however none of these use unitialized variables to my knowledge unless the predefined code generated by CubeMX is going beyond the bounds of the bss segment of memory and that the size of the bss segment is too large now for the board's memory (which I suspect is unlikely but can't rule out). LoopF​​illZerobss()at .. \\ startup / startup_stm32f334x8.s:103 103 cmp r2,r3在尝试实现LCD和ADC功能时,我在启动的LoopF​​illZerobss函数期间收到断点陷阱错误,这被证明是致命的 ,特别是通过阻止我的USART报告完全(但它仍然可以接收字节作为中断和处理令牌等,只是拒绝传输),在读入bss段后,我试图通过初始化尽可能多的全局变量来解决问题,非零值,这不起作用,在添加ADC的STM32CubeMx设置和LCD中使用的7个GPIO引脚后会出现问题,但是除非CubeMX生成的预定义代码超出了CubeMX的范围,否则它们都不会使用单元化变量。 bss段的内存和bss段的大小现在对于板的内存来说太大了(我怀疑它不太可能但不能排除)。

Essentially the idea of this project is to receive various data over USART, ADC and later I2C and display various aspects of the data over USART and LCD at currently if I discard the ADC and LCD errors my USART code functions as the memset() error is non-lethal but I suspect that leaving it there is only causing me later issues but I'm also not sure where to fix my tokenizing code, assuming it is the root of my issues. 基本上这个项目的想法是通过USART,ADC和后来的I2C接收各种数据,并在当前如果我丢弃ADC和LCD错误的USART和LCD上显示数据的各个方面我的USART代码用作memset()错误是非致命但我怀疑留下它只会导致我后来的问题,但我也不知道在哪里修复我的令牌化代码,假设它是我的问题的根源。

Essentially the source of my problem was misuse of sprintf and overwritting program code with null characters 基本上我的问题的根源是滥用sprintf并用空字符覆盖程序代码

By ensuring to use snprintf rather than sprintf with well defined sized strings I ran into no more memory issues. 通过确保使用snprintf而不是使用定义良好的字符串的sprintf ,我遇到了更多的内存问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM