在C中连接char数组:动态处理内存

时间:2016-06-05 23:14:37

标签: c arrays string

我对我在C程序中出错的原因感到困惑:我试图创建一个以'!'开头的字符串,并添加从传感器读取的6个值(用逗号分隔)然后通过串口发送。示例输出为:"!5,5,5,5,5,5""!34,34,34,34,34,34"

问题:因为传感器值(上例中的5或34)的范围可以从0到255,所以我在运行时不知道我的char数组需要多大。这意味着我每次要添加到字符串时都必须动态重新分配内存。下面是我尝试这样做的,但我做错了,因为我看到没有任何东西进入我的串口(表明存在运行时错误)。

如何正确实现代码以动态为字符串分配内存?我尝试使用mallocrealloc的行为不符合预期。

char* convertIntToString(uint8_t integerValue){
    char *str = malloc(4);          //up to 3 digits + 1 for null termination 
    utoa(integerValue, str, 10);
    return str;
}

char* concat(char *s1, char *s2)
{
    char *result = malloc(strlen(s1)+strlen(s2)+1);//+1 for the zero-terminator
    //in real code you would check for errors in malloc here
    strcpy(result, s1);
    strcat(result, s2);
    return result;
}

int main(void)
{
    uint8_t analogValue;
    char *outputStr = malloc(1);  //initalize size of char array = 1 element

    while (1) {
        outputStr = realloc(outputStr, 1);
        outputStr = concat(outputStr, "!");
        analogValue = ReadADC(0);
        outputStr = concat(outputStr, convertIntToString(analogValue));
        for(int i = 0; i < 5; i++){
            outputStr = concat(outputStr, ",");
            outputStr = concat(outputStr, convertIntToString(analogValue));
        }
        CDC_Device_SendString(&VirtualSerial_CDC_Interface, outputStr); //send string via USB
        free(outputStr);
    }  
}

2 个答案:

答案 0 :(得分:2)

由于在outputStr循环内的第一个语句中未正确初始化while的内容,因此您遇到了未定义的行为。

   outputStr = realloc(outputStr, 1); // outputStr is not initialized.

将它们更改为:

    outputStr = realloc(outputStr, 2);
    strcpy(outputStr, "!");

你也在泄漏一大堆内存。从convertToString返回的值绝不是free d。

您可以通过稍微改变策略来避免这个问题。

将函数更改为需要字符串并使用它。

char* convertIntToString(uint8_t integerValue,
                         char* str)
{
   utoa(integerValue, str, 10);
   return str;
}

然后,将其用法更改为:

    outputStr = concat(outputStr, convertIntToString(analogValue, str));

由于您使用concat的方式,您也在泄漏内存。

        outputStr = concat(outputStr, ",");

泄漏outputStr的旧值。您需要将outputStr的旧值保留更长时间才能free

以下是我对while循环的建议:

while (1) {

    outputStr = realloc(outputStr, 2);
    strcpy(outputStr, "!");

    analogValue = ReadADC(0);

    char str[4]; // This is the max you need.
                 // There is no need to malloc and free.

    outputStr = concat(outputStr, convertIntToString(analogValue, str));

    for(int i = 0; i < 5; i++){

        char* newStr = concat(outputStr, ",");

        // free the old memory before using the new memory
        free(outputStr);
        outputStr = newStr;

        newStr = concat(outputStr, convertIntToString(analogValue, str));

        // free the old memory before using the new memory
        free(outputStr);
        outputStr = newStr;
    }
    CDC_Device_SendString(&VirtualSerial_CDC_Interface, outputStr); //send string via USB
    free(outputStr);
}  

答案 1 :(得分:0)

以下代码:

  1. 消除了对malloc,free,realloc的不必要调用,因此(除此之外)没有内存泄漏
  2. 创建所需的字符串以输出
  3. 消除了不必要的子功能
  4. 生成正确的outputStr []数组内容
  5. 现在是代码:

    #include <string.h>
    
    int main(void)
    {
        uint8_t analogValue;
        char outputStr[20];  
        char temp[4];
    
        while (1)
        {
            memset( outputStr, 0, sizeof(outputStr) );
            outputStr = strcat(outputStr, "!");
    
            for(int i = 0; i < 5; i++)
            {
                 analogValue = ReadADC(0);
                 if( i < 4 )
                    sprintf( temp, "%u,", analogValue );
                 else
                    sprintf( temp, "%u", analogValue );
                strcat( outputStr, temp );
            }
    
            CDC_Device_SendString(&VirtualSerial_CDC_Interface, outputStr); //send string via USB
        }  
    }