潜在的内存溢出但不确定是什么原因造成的
A potential memory overflow but not sure what's causing it
我看到一个潜在的溢出:streamBuffer
是一个结构对象(FreeRTOS 库的一部分)并且在 OutputToSerial()
中执行以下行后,我看到 streamBuffer.xHead
's value 被设置为一个非常大的值,即使它当时没有被修改。
LONG_TO_STR(strData, txStr);
- 请注意,我之前多次调用
nRF24_ReadReg()
时没有遇到任何问题。
- 此外,我经常看到
printf
没有打印正在打印的整个文本(在我看到潜在溢出时调用时间之前)- 而是遗漏了一些字符。
有什么方法可以更好地了解原因?我在寄存器中没有看到任何硬故障或任何可查看的内容...
作为参考,以下是结构的定义:
typedef struct StreamBufferDef_t /*lint !e9058 Style convention uses tag. */
{
volatile size_t xTail; /* Index to the next item to read within the buffer. */
volatile size_t xHead; /* Index to the next item to write within the buffer. */
size_t xLength; /* The length of the buffer pointed to by pucBuffer. */
size_t xTriggerLevelBytes; /* The number of bytes that must be in the stream buffer before a task that is waiting for data is unblocked. */
volatile TaskHandle_t xTaskWaitingToReceive; /* Holds the handle of a task waiting for data, or NULL if no tasks are waiting. */
volatile TaskHandle_t xTaskWaitingToSend; /* Holds the handle of a task waiting to send data to a message buffer that is full. */
uint8_t *pucBuffer; /* Points to the buffer itself - that is - the RAM that stores the data passed through the buffer. */
uint8_t ucFlags;
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxStreamBufferNumber; /* Used for tracing purposes. */
#endif
} StreamBuffer_t;
// file.c
#define PRI_UINT64_C_Val(value) ((unsigned long) (value>>32)), ((unsigned long)value)
#define LONG_TO_STR(STR, LONG_VAL) (sprintf(STR, "%lx%lx", PRI_UINT64_C_Val(LONG_VAL)))
unsigned long long concatData(uint8_t *arr, uint8_t size)
{
long long unsigned value = 0;
for (uint8_t i = 0; i < size; i++)
{
value <<= 8;
value |= arr[i];
}
return value;
}
void nRF24_ReadReg(nrfl2401 *nrf, uint8_t reg, const uint8_t rxSize, uint8_t *rxBuffer, char *text)
{
uint8_t txBuffer[1] = {0};
uint8_t spiRxSize = rxSize;
if (reg <= nRF24_CMD_W_REG)
{
txBuffer[0] = nRF24_CMD_R_REG | (reg & nRF24_R_W_MASK);
spiRxSize++;
}
else
{
txBuffer[0] = reg;
}
nRF24_SendCommand(nrf, txBuffer, rxBuffer, spiRxSize);
OutputToSerial(txBuffer, rxBuffer, spiRxSize, text);
}
void OutputToSerial(uint8_t *writeBuffer, uint8_t *readBuffer, uint8_t size, char *text)
{
char strData[100] = {0}, rxStrData[100] = {0};
long long unsigned txStr = concatData(writeBuffer, size);
long long unsigned rxStr = concatData(readBuffer, size);
LONG_TO_STR(strData, txStr); // POTENTIAL ERROR.....!
LONG_TO_STR(rxStrData, rxStr);
char outputMsg[60] = {0};
strcpy(outputMsg, text);
strcat(outputMsg, ": 0x%s ----------- 0x%s\n");
printf (outputMsg, strData, rxStrData);
}
// main.c
StreamBufferHandle_t streamBuffer;
也许还有其他问题,但LONG_TO_STR(x)
简直是一团糟。
考虑值 0x123400005678
将打印为 "12345678"
。那个ref code坏了。
是的,它的代码太糟糕了 long long
但没有 "%llx"
。很容易 re-write 把它全部变成一个干净的函数。
//#define PRI_UINT64_C_Val(value) ((unsigned long) (value>>32)), ((unsigned long)value)
//#define LONG_TO_STR(STR, LONG_VAL) (sprintf(STR, "%lx%lx", PRI_UINT64_C_Val(LONG_VAL)))
#include <stdio.h>
#include <string.h>
#include <limits.h>
// Good for base [2...16]
void ullong_to_string(char *dest, unsigned long long x, int base) {
char buf[sizeof x * CHAR_BIT + 1]; // Worst case size
char *p = &buf[sizeof buf - 1]; // set to last element
*p = '[=10=]';
do {
p--;
*p = "0123456789ABCDEF"[x % (unsigned) base];
x /= (unsigned) base;
} while (x);
strcpy(dest, p);
}
int main(void) {
char buf[100];
ullong_to_string(buf, 0x123400005678, 16); puts(buf);
ullong_to_string(buf, 0, 16); puts(buf);
ullong_to_string(buf, ULLONG_MAX, 16); puts(buf);
ullong_to_string(buf, ULLONG_MAX, 10); puts(buf);
return 0;
}
输出
123400005678
0
FFFFFFFFFFFFFFFF
18446744073709551615
我看到一个潜在的溢出:streamBuffer
是一个结构对象(FreeRTOS 库的一部分)并且在 OutputToSerial()
中执行以下行后,我看到 streamBuffer.xHead
's value 被设置为一个非常大的值,即使它当时没有被修改。
LONG_TO_STR(strData, txStr);
- 请注意,我之前多次调用
nRF24_ReadReg()
时没有遇到任何问题。 - 此外,我经常看到
printf
没有打印正在打印的整个文本(在我看到潜在溢出时调用时间之前)- 而是遗漏了一些字符。
有什么方法可以更好地了解原因?我在寄存器中没有看到任何硬故障或任何可查看的内容...
作为参考,以下是结构的定义:
typedef struct StreamBufferDef_t /*lint !e9058 Style convention uses tag. */
{
volatile size_t xTail; /* Index to the next item to read within the buffer. */
volatile size_t xHead; /* Index to the next item to write within the buffer. */
size_t xLength; /* The length of the buffer pointed to by pucBuffer. */
size_t xTriggerLevelBytes; /* The number of bytes that must be in the stream buffer before a task that is waiting for data is unblocked. */
volatile TaskHandle_t xTaskWaitingToReceive; /* Holds the handle of a task waiting for data, or NULL if no tasks are waiting. */
volatile TaskHandle_t xTaskWaitingToSend; /* Holds the handle of a task waiting to send data to a message buffer that is full. */
uint8_t *pucBuffer; /* Points to the buffer itself - that is - the RAM that stores the data passed through the buffer. */
uint8_t ucFlags;
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxStreamBufferNumber; /* Used for tracing purposes. */
#endif
} StreamBuffer_t;
// file.c
#define PRI_UINT64_C_Val(value) ((unsigned long) (value>>32)), ((unsigned long)value)
#define LONG_TO_STR(STR, LONG_VAL) (sprintf(STR, "%lx%lx", PRI_UINT64_C_Val(LONG_VAL)))
unsigned long long concatData(uint8_t *arr, uint8_t size)
{
long long unsigned value = 0;
for (uint8_t i = 0; i < size; i++)
{
value <<= 8;
value |= arr[i];
}
return value;
}
void nRF24_ReadReg(nrfl2401 *nrf, uint8_t reg, const uint8_t rxSize, uint8_t *rxBuffer, char *text)
{
uint8_t txBuffer[1] = {0};
uint8_t spiRxSize = rxSize;
if (reg <= nRF24_CMD_W_REG)
{
txBuffer[0] = nRF24_CMD_R_REG | (reg & nRF24_R_W_MASK);
spiRxSize++;
}
else
{
txBuffer[0] = reg;
}
nRF24_SendCommand(nrf, txBuffer, rxBuffer, spiRxSize);
OutputToSerial(txBuffer, rxBuffer, spiRxSize, text);
}
void OutputToSerial(uint8_t *writeBuffer, uint8_t *readBuffer, uint8_t size, char *text)
{
char strData[100] = {0}, rxStrData[100] = {0};
long long unsigned txStr = concatData(writeBuffer, size);
long long unsigned rxStr = concatData(readBuffer, size);
LONG_TO_STR(strData, txStr); // POTENTIAL ERROR.....!
LONG_TO_STR(rxStrData, rxStr);
char outputMsg[60] = {0};
strcpy(outputMsg, text);
strcat(outputMsg, ": 0x%s ----------- 0x%s\n");
printf (outputMsg, strData, rxStrData);
}
// main.c
StreamBufferHandle_t streamBuffer;
也许还有其他问题,但LONG_TO_STR(x)
简直是一团糟。
考虑值 0x123400005678
将打印为 "12345678"
。那个ref code坏了。
是的,它的代码太糟糕了 long long
但没有 "%llx"
。很容易 re-write 把它全部变成一个干净的函数。
//#define PRI_UINT64_C_Val(value) ((unsigned long) (value>>32)), ((unsigned long)value)
//#define LONG_TO_STR(STR, LONG_VAL) (sprintf(STR, "%lx%lx", PRI_UINT64_C_Val(LONG_VAL)))
#include <stdio.h>
#include <string.h>
#include <limits.h>
// Good for base [2...16]
void ullong_to_string(char *dest, unsigned long long x, int base) {
char buf[sizeof x * CHAR_BIT + 1]; // Worst case size
char *p = &buf[sizeof buf - 1]; // set to last element
*p = '[=10=]';
do {
p--;
*p = "0123456789ABCDEF"[x % (unsigned) base];
x /= (unsigned) base;
} while (x);
strcpy(dest, p);
}
int main(void) {
char buf[100];
ullong_to_string(buf, 0x123400005678, 16); puts(buf);
ullong_to_string(buf, 0, 16); puts(buf);
ullong_to_string(buf, ULLONG_MAX, 16); puts(buf);
ullong_to_string(buf, ULLONG_MAX, 10); puts(buf);
return 0;
}
输出
123400005678
0
FFFFFFFFFFFFFFFF
18446744073709551615