C中的Memcpy导致STM在关闭和打开电源后冻结

v440hwme  于 2022-12-17  发布在  其他
关注(0)|答案(2)|浏览(142)

我有一个问题与stm32 f401 ccu。执行代码后,断开和连接电源的STM冻结,并解冻它,我需要重新加载构建。
我有一组复杂的函数,用于将一个int值数组转换为一个非常长的char数组。然后将char数组写入长期闪存。为了执行该操作,我对char数组进行了许多操作,它们 * 看起来 * 执行正确。因为保存到Flash是正确的-我用ST LINK测试了Flash内容,它们是应该的。但是在关闭电源/在实际测试长期闪存是否工作时,我遇到了一个致命的错误-在重新为STM供电时,它会冻结,唯一的解冻方法是重新加载构建。
经过几个小时的测试,我发现问题出在StringCreateStrForFlashOneProductmemcpy的使用上,可能是我造成了某种内存泄漏,但我不知道出了什么问题。
导致STM冻结的一段示例操作:

static char send_save_string_final[2048];
char sssssend_char[2048] = "000000NewProduct";
char *StringCreateStrForFlashOneProduct(const int someint)
{
    memcpy(sssssend_char, "000000008888008000000000888800800000000088880080", 48);
    memcpy(send_save_string_final, sssssend_char, 48);
    return send_save_string_final;
}

我实际使用的代码:
FUNCTION ONE -创建一个字符数组,然后将其保存到闪存

static char output_all_sorts[6001] = "";
char all_save_string[6001] = "";
char sssssend_char_all_sorts[2048] = "00000AllProducts";
char append_char_numz_all_sorts[17] = "0000000000000000";

void FlashSaveAllSorts(void)
{
    strcpy(sssssend_char_all_sorts, "00000AllProducts");
    sssssend_char_all_sorts[2047] = 0;

    strcpy(output_all_sorts, "0");
    output_all_sorts[6000] = 0;
    strcpy(all_save_string, "00000AllProducts");
    all_save_string[6000] = 0;
    strcpy(append_char_numz_all_sorts, "0000000000000000");
    append_char_numz_all_sorts[16] = 0;

    for (int doin_int = 0; doin_int <= 6; doin_int++)
    {
        strcpy(sssssend_char_all_sorts, StringCreateStrForFlashOneProduct(doin_int));
        strcat(all_save_string, sssssend_char_all_sorts);
        strcpy(output_all_sorts, all_save_string);
    }

    strcpy(output_all_sorts, all_save_string);

    output_all_sorts[strlen(output_all_sorts)] = 0;
    Flash_Write_Data(0x08020000, output_all_sorts, 3000);
}

FUNCTION TWO -为一个产品创建包含所有数据的单行

static char send_save_string_final[2048] = "0";
char sssssend_char[2048] = "000000NewProduct";
char append_char_numz[17] = "0000000000000000";

char *StringCreateStrForFlashOneProduct(const int someint)
{
    strcpy(send_save_string_final, "0");
    send_save_string_final[2047] = 0;
    strcpy(sssssend_char, "000000NewProduct");
    sssssend_char[2047] = 0;
    strcpy(append_char_numz, "0000000000000000");
    append_char_numz[16] = 0;

    strncpy(append_char_numz, StringCreateStringFromIntTwo(someint), 17);
    append_char_numz[16] = 0;
    strcat(sssssend_char, append_char_numz);

    for (int kk = 0; kk < 3; kk = kk + 1)
    {
        char append_char_one[17] = "0000000000000000";

        for (int jj = 0; jj < 12; jj = jj + 1)
        {
            char append_char[17] = "0000000000000000";

            memcpy(append_char, StringCreateStringFromIntTwo(tunable_vars_machine_for_flash[someint][kk][jj]), 17);

            strcat(sssssend_char, append_char);
        }

        memcpy(append_char_one, "000000000MenuEnd", 17);
        strcat(sssssend_char, append_char_one);
    }

    char append_char_end_zeros[17] = "0000000000000000";
    memcpy(append_char_end_zeros, StringCreateStringFromIntTwo(0), 17);
    strcat(sssssend_char, append_char_numz);

    memcpy(send_save_string_final, sssssend_char, 2047);
    return send_save_string_final;
}

功能三-创建一个16字符数组,格式为0000000000000001333,零是保持保存字符串长度一致所必需的,1333是示例数据值:

char *StringCreateStringFromIntTwo(int base_int_base)
{
    //clearprint("StringCreateStri");
    int base_int = base_int_base;

    if (base_int == 0)
    {
        base_int = 999999; /// avoid saving zero to flash memory
    }

    static char send_char_final[17]  = "0000000000000000";
    char send_char[16]  = "00000000";
    static char send_char_sixteen_zeros[17] = "0000000000000000";

    int legnewpigwphjh = strlen(send_char);

    char str_zero[2] = "0";
    char str_two_zeros[3] = "00";
    char str_three_zeros[4] = "000";
    char str_four_zeros[5] = "0000";
    char str_five_zeros[6] = "00000";
    char str_six_zeros[7] = "000000";
    char str_seven_zeros[8] = "0000000";
    char str_eight_zeros[9] = "00000000";
    char str_sixteen_zeros[17] = "0000000000000000";

    int int_mem_length = countDigits(base_int);

    char str_mem_write_int[9];
    sprintf(str_mem_write_int, "%d", base_int);

    if (int_mem_length == 7)
    {
        strcat(send_char, str_zero);
    }
    if (int_mem_length == 6)
    {
        strcat(send_char, str_two_zeros);
    }
    if (int_mem_length == 5)
    {
        strcat(send_char, str_three_zeros);
    }
    if (int_mem_length == 4)
    {
        strcat(send_char, str_four_zeros);
    }
    if (int_mem_length == 3)
    {
        strcat(send_char, str_five_zeros);
    }
    if (int_mem_length == 2)
    {
        strcat(send_char, str_six_zeros);
    }
    if (int_mem_length == 1)
    {
        strcat(send_char, str_seven_zeros);
    }

    strcat(send_char, str_mem_write_int);

    strcpy(send_char_final, str_sixteen_zeros);
    strcpy(send_char_final, send_char);

    return send_char_final;
}
tgabmvqs

tgabmvqs1#

你的代码太复杂了。有太多的字符串复制和连接,以及无数无用的操作。你似乎没有掌握指针,也没有基本的内存布局概念。最重要的是,考虑到你的技能水平,你绝对应该避免strncpymemcpy
下面是一个更简单的方法,它使用函数在缓冲区的末尾构造适当的字符串格式,并返回写入的字符数。使用这个方法,编写一个长字符串要简单得多,也更不容易出错:

// function to construct a fixed length string of digits with leading 0s
// buffer must point to an array at least 17 bytes long
// returns the number of characters, ie: 16
int FormatNumber16(char *buffer, int someint) {
    if (someint == 0) {
        // This test seems bogus: the product number 0 will be written as 999999
        // and so will the MenuEnd number
        someint = 999999;  // avoid writing 0 ???
    }
    return snprintf(buffer, 17, "%016d", someint);
}

// function to construct the product string to store to flash
// buffer must point to an array at least 641 bytes long
// returns the number of characters, ie: 640
int FormatOneProduct(char *buffer, int product_nb) {
    int pos = 0;

    pos += snprintf(buffer + pos, 17, "%016s", "NewProduct");  
    pos += FormatNumber16(buffer + pos, product_nb);  

    for (int kk = 0; kk < 3; kk++) {
        for (int jj = 0; jj < 12; jj++) {
            pos += FormatNumber16(buffer + pos, 
                       tunable_vars_machine_for_flash[product_nb][kk][jj]);
        }
    }
    pos += snprintf(buffer + pos, 17, "%016s", "MenuEnd");  
    // vvv this will actually append 0000000000999999 ?
    pos += FormatNumber16(buffer + pos, 0);
    // pos should be 640 = 16 + 16 + 12*3*16 + 16 + 16
    return pos; 
}

// function to write all product data to flash (7 products)
void FlashSaveAllSorts(void) {
    char buffer[6001] = "";   // no need for global data
    int pos = 0;

    pos += snprintf(buffer + pos, 17, "%016s", "AllProducts");  

    // append the description of all 7 products (0 to 6 included)
    for (int product_nb = 0; product_nb <= 6; product_nb++) {
        pos += FormatOneProduct(buffer + pos, product_nb);
    }
    // buffer contains 4496 = 16 + 640*7 characters, why write 3000 bytes?
    Flash_Write_Data(0x08020000, buffer, 3000);
}
y4ekin9u

y4ekin9u2#

一些示例函数:

char *StringCreateStrForFlashOneProduct(char *buff, size_t len, int someint)
{
    int mask = 1000000000;
    char *wrk = buff;

    if(!someint) someint = 999999;
    memset(buff, '0', len - 10);
    wrk += len - 10;
    while(mask)
    {
        *wrk++ = '0' + abs(someint / mask);
        someint %= mask;
        mask /= 10;
    }
    *wrk = 0;
    return buff;
}

示例用法:

int main(void)
{
    char str[17];

    printf("`%s`\n", StringCreateStrForFlashOneProduct(str, 16, 1234));
}

相关问题