Элементы массива изменяются после возврата из функции в C - PullRequest
0 голосов
/ 10 февраля 2019

У меня есть простая программа на C, работающая на архитектуре ARM.У нас есть два глобальных массива:

char RxB[400];
char GPS[150];

У меня есть такая функция, которая ищет и находит подстроку между key и termChar.Подстрока результата определяется как параметр функции:

SEARCH_STATUS findString_chr(char *src, char *key, int key_size, char termChar, char *dst, int desLen)
{
    char *temp, *tempchar;
    temp = strstr(src, key);
    if (temp == NULL)
        return STR_KEY_NOT_FOUND;
    else
        temp += key_size;

    tempchar = strchr(temp, termChar);
    if (!tempchar)
        return STR_TERMINATOR_NOT_FOUND;

    uint8_t siz = (uint8_t)(tempchar - temp);
    if (siz > desLen)
        return STR_OVERFLOW;
    memcpy(dst, temp, siz);
    dst[siz] = '\0';
    return STR_FOUND;
}

В моем main.c у меня есть простой код, подобный этому:

do {
    ST = findString_chr(RxB, key, strlen(key), '$', GPS, 150);
    // Some delay here
    // Some other codes
} while (some conditions);

Примечаниечто значение RxB меняется каждую 1 секунду, поскольку оно получается из последовательной связи.

Моя проблема в том, что, как я знаю, после выхода из функции findStringchr значение GPS не должнобыть изменены, потому что никто не манипулирует его элементами.Но когда я отлаживаю свой код, я вижу, что значение массива GPS все еще меняется.

У кого-нибудь есть идеи?

PS: main.c более подробно:

    cnt = 0;        
    HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);

    do {
        ST = findString_chr(RxB, key, strlen(key), '$', GPS, 150);
        findString_chrchr(GPS, 2, st, 2);
        if ((st[0] == 'A') && (ST == STR_FOUND)) {
            findString_chrchr(GPS, 3, lati, 10);
            findString_chrchr(GPS, 5, longi, 11);  
            sendState = GPS_ACTIVE;
            HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
            HAL_Delay(1000);    
            HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
            HAL_Delay(1000);    
            HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
            HAL_Delay(1000);    
            HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
            HAL_Delay(1000);                    
            HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin,GPIO_PIN_RESET); 
        }
        HAL_Delay(1000);
        HAL_IWDG_Refresh(&hiwdg);           
        gpsCounter++;
        if (gpsCounter > (TIMEOUT_GPS/1000)) {      
            sendState = GPS_TIMEOUT;
            memcpy(lati, "1111.1111", 10);
            memcpy(longi, "01111.1111", 11);    
            gpsCounter = 0;
        }
    } while ((sendState == GPS_VOID) && (cnt != 1));

Функция findStringchrchr() возвращаетподстрока между двумя последующими запятыми:

SEARCH_STATUS findString_chrchr(char *src, int commaNumber, char *dst, int desLen) {
    char *temp = src, *end;
    int cnt = 0;
    while (1) {
        temp = strchr(temp, ',') + 1;
        if (!temp)
            return STR_KEY_NOT_FOUND;
        else {
            cnt++;
            if (cnt == commaNumber) {
                end = strchr(temp, ',');
                int D = (end - temp);
                if (D >= desLen)
                    return STR_OVERFLOW;
                if (D == 0)
                    dst[0] = '\0';
                } else {
                    memcpy(dst, temp, D);
                    dst[D] = '\0';
                }   
                break;
            }
        }
    }
    return STR_FOUND;
}

Ответы [ 2 ]

0 голосов
/ 10 февраля 2019

Ваш вопрос не предоставляет достаточно информации для полной диагностики. Неясно, что вы подразумеваете под , значение GPS не должно изменяться, потому что никто не манипулирует его элементами .Вот несколько идей:

  • По диагнозу Джонатана, GPS изменяется вашей функцией findString_chr, если ключ найден.Вы не ожидали этого?

  • вы наблюдаете, как содержимое глобального массива GPS будет изменено после вызова findString_chr()?Вы не опубликовали соответствующий код, вполне возможно, что это вызвано побочным эффектом.

У самой функции findString_chr есть проблемы:

  • Тип uint8_t в uint8_t siz = (uint8_t)(tempchar - temp); типичен для практики разработки встроенного программного обеспечения, поддерживаемой некоторым стандартом кодирования с очень плохими побочными эффектами: если расстояние между temp и tempchar больше, чем 256, оно не даетсмысл, принимающий только бессмысленную часть значения, siz должен иметь тип int или size_t, а использование int8_t не экономит место во время выполнения, это просто ошибка.

  • Тест if (siz > desLen) выключен на 1. Пространство, требуемое в массиве назначения, составляет siz+1 байт для учета нулевого терминатора, который вы устанавливаете в смещение siz.

Вот исправленная версия:

SEARCH_STATUS findString_chr(const char *src, const char *key, int key_size,
                             char termChar, char *dst, int desLen) {
    const char *temp, *tempchar;
    int siz;

    temp = strstr(src, key);
    if (temp == NULL)
        return STR_KEY_NOT_FOUND;

    temp += key_size;
    tempchar = strchr(temp, termChar);
    if (!tempchar)
        return STR_TERMINATOR_NOT_FOUND;

    siz = tempchar - temp;
    if (siz >= desLen)
        return STR_OVERFLOW;

    memcpy(dst, temp, siz);
    dst[siz] = '\0';
    return STR_FOUND;
}

Относительно вашей проблемы Отправка полного исходного кода в минимальную программу, демонстрирующую проблему, может быть неосуществимой, но тип ошибки, присутствующий в functiна findString_chr может присутствовать в другом месте и привести к повреждению памяти.Например, возможно, что подпрограммы последовательной связи, записывающие в RxB, переполняют конец этого массива, который, учитывая глобальные объявления, упомянутые в вопросе, может находиться непосредственно перед массивом GPS в ОЗУ.

РЕДАКТИРОВАТЬ: После размещения дополнительной информации возникают дополнительные проблемы:

  • Вы безоговорочно звоните findString_chrchr(GPS, 2, st, 2);, даже если findString_chr не возвращает STR_FOUND.Это проблема, потому что findString_chrchr имеет неопределенное поведение, если количество запятых в строке слишком мало.

Действительно, функция findString_chrchr имеет проблемы:

  • После строки if (D == 0) dst[0] = '\0'; имеется дополнительный }, в результате чего блок else связывается с внешним if.

  • temp = strchr(temp, ',') + 1; не будетNULL из ',' не найдено.Вы должны проверить temp перед его увеличением.

  • вы не проверяете, есть ли еще , при вычислении длины для копирования.int D = (end - temp); может быть отрицательным, если temp равно NULL, вызывая неопределенное поведение.

Вот исправленная и упрощенная версия:

SEARCH_STATUS findString_chrchr(const char *src, int commaNumber, char *dst, int desLen) {
    /* skip commaNumber fields */
    while (commaNumber > 0) {
        src = strchr(src, ',');
        if (!src)
            return STR_KEY_NOT_FOUND;
        src++;
        commaNumber--;
    }
    int D = 0;
    while (src[D] != '\0' && src[D] != ',')
        D++;
    if (D >= desLen)
        return STR_OVERFLOW;
    if (D > 0)
        memcpy(dst, src, D);
    dst[D] = '\0';
    return STR_FOUND;
}
0 голосов
/ 10 февраля 2019

Вы передаете GPS в положение, соответствующее параметру dst в функции.

В функции вы получаете:

memcpy(dst,temp,siz);

Это, безусловно, изменяет массивGPS когда оно выполнено, поэтому ваше утверждение, что "значение GPS не должно изменяться, потому что никто не манипулирует его элементами" просто неверно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...