C 为什么在向FreeRTOS队列传递指针时会出现堆损坏错误?

C 为什么在向FreeRTOS队列传递指针时会出现堆损坏错误?,c,queue,freertos,task-queue,C,Queue,Freertos,Task Queue,我正在和一个正在使用和的用户一起工作 我使用单个队列从多个任务(传感器读数)收集数据。单个队列接收器将通过TCP套接字输出数据。因为队列项目相当大,所以我决定只放一个指向队列项目的指针,只要内存处理正确,根据需要这应该可以 这是我用于队列项目的数据结构,请注意结构末尾的灵活数组: typedef struct mb32_packet_t { uint16_t preamble; uint8_t system_id; uint8_t message_id; ui

我正在和一个正在使用和的用户一起工作

我使用单个队列从多个任务(传感器读数)收集数据。单个队列接收器将通过TCP套接字输出数据。因为队列项目相当大,所以我决定只放一个指向队列项目的指针,只要内存处理正确,根据需要这应该可以

这是我用于队列项目的数据结构,请注意结构末尾的灵活数组:

typedef struct mb32_packet_t {
    uint16_t preamble;
    uint8_t  system_id;
    uint8_t  message_id;
    uint8_t  reserved;
    uint16_t checksum;
    uint32_t pay_len;
    uint8_t  payload[];
} __attribute__((packed)) mb32_packet_t;
队列声明和定义:

#define MAX_QUEUE_SEND_ITEMS (25)

QueueHandle_t sys_link_send_queue;

sys_link_send_queue = xQueueCreate(MAX_QUEUE_SEND_ITEMS, sizeof(mb32_packet_t*));
以下是将项目放入队列的传感器读取任务之一的片段:

mb32_packet_t *packet;
uint32_t pay_len = 8;                        // payload: 8 bytes
uint32_t pac_len = sizeof(*packet)+pay_len;  // header: 11 bytes
packet = malloc(pac_len);
// ... code to assign header fields
// ... code to assign payload bytes

if(xQueueSend(sys_link_send_queue, &packet, portMAX_DELAY) != pdPASS) {
    // release allocated memory in case the queue rejected the item
    free(packet);
}
以下是单个接收器的片段:

void sys_link_task(void *pvParameters) {
    while(1) {
        mb32_packet_t* packet;
        if(xQueueReceive(sys_link_send_queue, &packet, portMAX_DELAY) == pdPASS) {
            // put packet bytes on the TCP stream (blocking mode)
            tcp_server_send((uint8_t*)packet, packet->pay_len+11);
            // finally release the packet memory
            free(packet);
        } else {
            ESP_LOGE(TAG, "Failed to get message from queue.");
        }
    }
}
最后,这是
tcp\u server\u send()函数的实现:

void tcp_server_send(uint8_t* buffer, size_t size) {
    // send() can return less bytes than supplied length. Walk-around for robust implementation.
    if(client_sock > 0) {
        int to_write = size;
        while(to_write > 0) {
            int written = send(client_sock, buffer+(size-to_write), to_write, 0);
            if(written < 0) {
                printf("Failed to send data [w=%d]: %d", written, errno);
                break;
            }
            to_write -= written;
        }
    }
}
然后我运行
xtensa-esp32-elf-gdb
,并在程序计数器(PC)上查找符号:

你知道如何解决这个问题吗?

我的想法:

  • 我是否过早释放数据包内存?尽管据我所知,TCP套接字处于阻塞状态(默认设置)。但是,如果TCP套接字不处于阻塞状态,则在使用单个传感器任务时,它也可能不工作。因此,我猜我在队列本身或内存分配/释放方面做错了什么

  • 我还尝试使用
    pvPortMalloc()
    而不是
    malloc()
    vPortFree()
    而不是
    free()
    。但没有区别,同样的问题


问题中描述的队列处理应该可以。请与FreeRTOS论坛上的进行比较

从Github更新到最新的ESP-IDF后,问题消失了

CORRUPT HEAP: multi_heap.c:288 detected at 0x3ffc75e8
abort() was called at PC 0x4008da2e on core 1

ELF file SHA256: c4fc5b20ae785f9a890274f05fd4fcfcada76b29ea16a9f736ceabbea34086ad

Backtrace: 0x400913e9:0x3ffc95c0 0x40091785:0x3ffc95e0 0x4008da2e:0x3ffc9600 0x4008dda5:0x3ffc9620 0x4008413d:0x3ffc9640 0x4008416d:0x3ffc9660 0x40093a71:0x3ffc9680 0x40094557:0x3ffc96a0 0x400f4946:0x3ffc96c0 0x400f4987:0x3ffc96e0 0x400f4b0d:0x3ffc9700 0x400f4e8e:0x3ffc9720 0x400f4ee5:0x3ffc9770 0x400e2e43:0x3ffc97a0 0x400e2f52:0x3ffc97d0 0x400d3f89:0x3ffc97f0 0x4000bd83:0x3ffc9810 0x4000182a:0x3ffc9830 0x400d5e9c:0x3ffc9850 0x400d608c:0x3ffc9880 0x40093cd1:0x3ffc98b0

CPU halted.
PC 0x4008da2e -> split_if_necessary + 206 in section .iram0.text