Sending a string via a queue problem

Hi All,
So im trying to send a string but getting weird string in the receive function.

    char *recievedData;
    char *recievedDataFromQ;
    meshQueue = xQueueCreate(1, sizeof(uint32_t));

   void onReceiveData(const uint8_t *mac, const uint8_t *data, int len){

     //convert uint_t to string
    recievedData = (char *)data;

    //sending/////
    if  (xQueueSend(meshQueue, &recievedData, 0) != pdPASS)
        ESP_LOGE(MeshTAG, "Failed to send sensor data to network");
    else
        ESP_LOGI(MeshTAG, "Added [%s] to the queue", 
        recievedData);
      }

      ////receiving//
      if (xQueueReceive(meshQueue, &recievedDataFromQ, 0))
      {
          ESP_LOGI(MeshTAG, " Read [%s] from the queue", 
          recievedDataFromQ);
      }


the last one prints so random string [SP_D57B…].

note: if i assign a string value to receivedData it works fine.
so instead of
recievedData = (char *)data;
i do
recievedData = “some string”;

it works with absolutely no problem.
is the problem with the way im creating the queue and the size? or is it because im using a char*?
any help would be highly appreciated.
thanks

It’s a good idea to get a bit more familiar with queues before using them :wink:
It’s well documented e.g. here and in the API docs there with examples.
However, queues are item based. So creating a queue of (1 ?) uint32_t sized item(s) implies sending receiving uint32_t items. Not strings consisting of char items. Otherwise things will usually get messed up. You might send pointers to chars but take care about the lifetime of the source string not being temporary data on the stack or a buffer getting overwritten.
For more complex data or messages define a corresponding fixed size structure and create a queue of that type…
Good luck :slight_smile:

1 Like

@hs2 thank you so much for the reply.
I’m a web developer, never done C before. But found myself forced to do this to cover for a very sick friend.
I also tried this
meshQueue = xQueueCreate(250, sizeof(char*));

and it prints out fine the first time, then goes back to putting out the same string [SP_D7DB75����0`].

why does it work fine when i declare the received data?
no matter how long the string declared…it work.

Hmmm… If you’ve to deal with say unformatted bytes or just text forwarded from one task to another task you should consider to use streambuffers. A feature provided by decent versions (I think v10 and later) of FreeRTOS.
Your last example creates a queue of 250 (char*) items which means 250 * 4 bytes on a 32 bit platform. I guess you tried to create a queue which can hold 250 chars which is 250 * 1 byte.
But variable length text is hard to handle with queues or at least causes a lot of overhead.
Consider either send/receive of padded strings of fixed length (Q item size is the fixed length then) or malloc a buffer on the sending side, copy the sensor data into it, send the pointer of that buffer (Q item size is sizeof(char*) ). The receiver receives the pointer of that buffer and can free it after final usage of the data. So the latter alternative deals just with (char*) items pointing to the sensor data.
If you can ensure that the source buffer is not overwritten by new incoming data while the receiving task accesses this buffer you could also use a single (persistent) static or global buffer to avoid dealing with dynamically allocated heap buffers.
It’s important that local data e.g on stack of a task can’t be safely used by another task.
It might seem to work but it isn’t because the stack data is not yet re-used but next time it is and you’re accessing completely different data.
I hope it’s getting more clear. Which is surely hard for a web developer forced to do good old C. I feel with you…

1 Like

While passing pointers with a queue can work, the key to remember is that if you do that then the data pointed to by the pointer isn’t saved anywhere, so the buffer that hold it needs to stick around until it is used on the receiving side, and not changed. One thing that means is that the receiver of the data tends to need some return channel to indicate it is done with the buffer (or maybe it is done with dynamic memory and the receiver just needs to free it).

@hs2 I cant thank you enough. Gave malloc and free a try and it worked like a charm.
embedded programming is 7 million times harder than working with angular, react and nodeJS :smiley:
thanks again

Great that you got it working :+1:
One last word regarding a common pitfall of embedded multi-tasking…
Your heap implementation (malloc/free) must be thread-safe or you’ve to use appropriate wrappers as FreeRTOS does (see FreeRTOSConfig.h::pvPortMalloc, vPortFree) .
In general e.g. when making use of (3rd party) C-libraries it’s usually required to ensure thread-safeness of malloc/free/etc. because you do not exactly know, whether some library functions are calling malloc internally or not.
I hope that your ESP SDK provides this for you :slight_smile:
Better verify the SDK docs if this is the case !
Otherwise you might get hit by pretty nasty, hard to detect and to find ‘heap corruption’ bugs.

You sir are right. It worked fine the last time and now the first 3 characters of my string is always corrupt. Digging deeper into the docs hoping to find a solution.

I guess you have pvPortMalloc and vPortFree defined in FreeRTOSConfig.h and implemented properly i.e. being thread safe. Using them should eliminate heap corruption as reason of this problem. Well, at least if no other code corrupts the heap…
You should also #define configCHECK_FOR_STACK_OVERFLOW 2 in FreeRTOSConfig.h when debugging which helps detecting hard to find stack overflows.
Good luck !