使用C语言的嵌入式系统中可靠的字符串连接

时间:2014-12-12 07:45:03

标签: c embedded concat strcat

我目前正在开发一段代码,它将通过以太网将一些XML数据作为字符串发送。应首先构造数据,以便发送到套接字。我正在使用STM32F4xx型微控制器并使用IAR EWARM嵌入式开发环境。

我一直在使用以下功能:

char* concat(char *s1, char *s2)
{
    size_t len1 = strlen(s1);
    size_t len2 = strlen(s2);
    char *result = malloc(len1+len2+1);//+1 for the zero-terminator
    //in real code you would check for errors in malloc here
    memcpy(result, s1, len1);
    memcpy(result+len1, s2, len2+1);//+1 to copy the null-terminator
    return result;
}

char* data = concat("<data>\n<items>\n<radar x=\"", "1"); 
data = concat(data, "\"></radar>\n<radar v=\"");
data = concat(data, "1");
data = concat(data, "\"></radar>\n</items>\n</data>");
len = strlen(data);

Socket_Send(data,len);

以太网服务器输出结果如下:

Send:(09:41:17) alive
Rec:(09:41:17)<data>
<items>
<radar x="1"></radar>
<radar v="1"></radar>
</items>
</data>
Send:(09:41:18) alive
Rec:(09:41:18)<data>
<items>
<radar x="1"></radar>
<radar v="1"></radar>
</items>
</data>
Send:(09:41:18) alive
Rec:(09:41:18)<data>

它正确发送数据2次,然后只写入6个字符。我该如何解决?任何帮助是极大的赞赏。提前谢谢..

编辑1: 建议代码:

data = concat("<data>\n<items>\n<radar x=\"", "1"); 
char *tmp = data;
data = concat(data, "\"></radar>\n<radar v=\"");
free(tmp);
data = concat(data, "1");
data = concat(data, "\"></radar>\n</items>\n</data>");

len = strlen(data);

输出:

Send:(09:51:38) alive
Rec:(09:51:38)<data>
<items>
<radar x="1"></radar>
<radar v="1"></radar>
</items>
</data>
Send:(09:51:40) alive
Rec:(09:51:40)<data>
<items>
<radar x="1"></radar>
<radar v="1"></radar>
</items>
</data>
Send:(09:51:44) alive
Rec:(09:51:44)<data>
<items>
<radar x="1"></radar>
<radar v="1"></radar>
</items>
</data>
Send:(09:51:44) alive
Rec:(09:51:44)8 ¹Õ"></radar>
</items>
</data>
Send:(09:51:44) alive
Rec:(09:51:44)8 ¹Õ1"></radar>
</items>
</data>
Send:(09:51:45) alive
Rec:(09:51:45)8 ¹Õ1"></radar>
</items>
</data>
Send:(09:51:45) alive
Rec:(09:51:45)8 ¹Õ
Send:(09:51:45) alive
Rec:(09:51:45)8 ¹Õ
Send:(09:51:46) alive
Rec:(09:51:46)8 ¹Õ
Send:(09:51:46) alive
Rec:(09:51:46)8 ¹Õ

编辑2(贫困解决方案):

char* data;
char* data1;
char* data2;
char* data3;
data1 = concat("<data>\n<items>\n<radar x=\"", "1"); 

data2 = concat(data1, "\"></radar>\n<radar v=\"");
free(data1);

data3 = concat(data2, "1");
free(data2);

data = concat(data3, "\"></radar>\n</items>\n</data>");
free(data3);

len = strlen(data);
Socket_Send(data,len);
free(data);

编辑3(求助):

当XML中的标签数量增加时,内存泄漏就像预期的那样发生。正如人们建议的那样,我已经尝试了 strcat 并且它有效。但是strcpy在我的编译器中不起作用。我强烈建议任何有同样问题的人使用strcat。

2 个答案:

答案 0 :(得分:1)

你在下面的电话中做了很多内存泄漏:

data = concat(data, "\"></radar>\n<radar v=\"");

纠正泄漏,您的程序应该按预期工作。

一种可能的解决办法:

{
  char *tmp = data;
  data = concat(data, "\"></radar>\n<radar v=\"");
  free(tmp);
}

同样在malloc之后,检查分配是否成功。

答案 1 :(得分:1)

根据需要上下文,您还可以重新编写concat函数。让它将可重新分配的缓冲区作为第一个参数。然后将其释放到内部分配并返回新的ptr。

char *concat(char *s1, char *s2)
{
    size_t len1 = s1 ? strlen(s1) : 0;
    size_t len2 = strlen(s2) + 1;
    char *result;

    result = malloc(len1 + len2);
    memcpy(result, s1, len1);
    memcpy(result + len1, s2, len2);
    free(s1);

    return result;
}

然后在你的其他代码中说:

size_t len;
char *data = NULL;

data = concat(data, "<data>\n<items>\n<radar x=\"");
data = concat(data, "1");
data = concat(data, "\"></radar>\n<radar v=\"");
data = concat(data, "1");
data = concat(data, "\"></radar>\n</items>\n</data>");


Socket_Send(data, strlen(data));
free(data);

作为一个侧面点,有时可以将数据转储到控制台 - 以验证它是否正确。做类似的事情:

#include <ctype.h>

void dump_txt(const char *buf, int len)
{
    int i;

    fprintf(stdout, "  ");
    for (i = 0; i < len; ++i)
        fprintf(stdout, "%c", isprint(buf[i]) ? buf[i] : '.');
    fprintf(stdout, "\n");
}

void dump(const char *buf, int len, int width)
{
    int i, k;

    for (i = 0; i < len; ++i) {
        if (i && !(i % width))
            dump_txt(buf + (i - width), width);
        fprintf(stdout, "%02x ", buf[i]);
    }
    k = i;
    for (k = i ; k % width; ++k)
        fprintf(stdout, "   ");
    dump_txt(buf + (i - (i % width)), k - i);
}

然后你可以说:

len = strlen(data);
dump(data, len + 1, 8); /* +1 to include trailing zero */
free(data);

应该给你类似的东西:

3c 64 61 74 61 3e 0a 3c   <data>.<
69 74 65 6d 73 3e 0a 3c   items>.<
72 61 64 61 72 20 78 3d   radar x=
22 31 22 3e 3c 2f 72 61   "1"></ra
64 61 72 3e 0a 3c 72 61   dar>.<ra
64 61 72 20 76 3d 22 31   dar v="1
22 3e 3c 2f 72 61 64 61   "></rada
72 3e 0a 3c 2f 69 74 65   r>.</ite
6d 73 3e 0a 3c 2f 64 61   ms>.</da
74 61 3e 00               ta>.