10 years ago.

String concatenation problem

Hi, I've a problem with concatenating strings using append function. I have to catch the SIM imei and to concatenate it with a long string of data. The first iteration the firmware executes perfectly, from the second time on the imei it's wrong in spite of using the same append function.

example of correct output: imei=353814352502123&dati[0][dt]=2014-05-19 06:49:07&dati[0][lat]=72.555592&dati[0][long]=140.711562

example of wrong output: imei=353814352502123L7&dati[29][dt]=2014-05-19 06:49:37&dati[29][lat]=72.555527&dati[29] [long]=140.71145

as if the function snprintf(im+6,16,"%s",devStatus.imei); mistaken something in compositing the string with the imei.

Do you have any suggestion?

Thanks a lot, Emmanuele

notice: "im" is defined like this char im[]="\nimei=";

posted by Emmanuele Polito 19 May 2014

Can you share code snippet how do you concatenate those data?

posted by Martin Kojtal 19 May 2014

char im[]="\nimei=";

snprintf(im+6,16,"%s",devStatus.imei); strcat(im,post_ptr); if(DEBUG_send) pc.printf("strcat %s\r\n",im);

string imei=""; imei.append(im); if(DEBUG_send) pc.printf("IMEI contiene: %s\n\r",imei.c_str());

posted by Emmanuele Polito 19 May 2014

Not a solution to your problem but from what you said im is defined in a way that reserves 6 bytes of memory and then you add up to 16 more characters to it without reserving that memory first. Unless you missed something out from the above examples you're lucky the program doesn't just crash.

posted by Andy A 19 May 2014

1 Answer

10 years ago.

No idea if this will solve the problem since that depends on the contents of devStatus.imei and port_ptr. But it should at least prevent memory corruption.

#define _maxLength_ 30

char im[_maxLength_];
snprintf(im,_maxLength_ ,"\nimei=%s%s",devStatus.imei,post_ptr);

OK, silly error, _maxLength_ clearly should be more like 80 or so given the length of the string you end up with.

posted by Andy A 19 May 2014

thanks a lot Andy, but I need the im dimension to be dinamic because post_ptr could be very large.

posted by Emmanuele Polito 19 May 2014

Well you either need to reserve the memory for it or keep post_ptr as a separate variable rather than concatenating it onto the end of the string.

If you really want to make it into one long string then you either need to make the string large enough that you never run out of space, chop the end off if it's over a certain length or allocate the memory dynamically.

Two ways to allocate the memory dynamically:

//the c way, manually handle the memory
char *im = (char *)malloc(sizeof(char) * (6+strlen(devStatus.imei) + strlen(post_ptr) + 1));
sprintf(im,"\nimei=%s%s",devStatus.imei,post_ptr);
[do something]
free(im);

//the c++ way, let the string data type handle the memory.
string im = "\nimea=";
string.append(devStatus.imei);
string.append(post_ptr);

posted by Andy A 19 May 2014

yes, I know, but the length of post_ptr changes during the execution, so could I change _maxLength_ in runtime?

posted by Emmanuele Polito 19 May 2014

You can't change the size of an array at runtime, it needs to be a constant.

However the c example above is effectively doing that for you.

char *myArray = (char *)malloc(sizeof(char) * A_NUMBER);
//and 
char myArray[A_NUMBER];

Both do they same thing, in c an array is just a pointer to the start of a block of memory. In this case they both reserve a block of memory A_NUMBER bytes long and give you a char pointer to the start of it. In both cases you can do exactly the same things with the variable myArray once it's been declared.

There are two big differences, using malloc you can change the size during execution and you have to remember to free the memory when you are finished with it.

(There are also speed differences and whether the memory is taken from the stack or the heap but those are performance issues rather than whether the code will work or not.)

posted by Andy A 19 May 2014

While you cannot change the length of an array once it is set, you are allowed to have it done by a runtime variable. In your example, A_NUMBER may be a non-constant variable. The stack doesn't care if it is determined at runtime or compiletime how long it is.

So in general I would also advice that method: malloc/new can be very powerful, but if it isn't required it is just an additional risk.

posted by Erik - 19 May 2014