C ++: Почему этот код вызывает у меня проблемы с памятью / неопределенное поведение? - PullRequest
1 голос
/ 20 июня 2019

Немного предыстории, если вам интересно ...

Следующий фрагмент кода - это попытка реализовать генератор кода ошибки пакета с использованием циклической проверки избыточности (CRC-15),Это используется для обнаружения повреждения данных связи.Более подробное введение не требуется.

Код и проблемы

init_PEC15_Table - это генератор таблицы поиска.

Функция pec15 принимает ввод данных, вычисляет адрес решения и находит результат в таблице соответствия.

data - это массив символов, которому я присвоил значение 1.Это будет передано в pec15.

Теперь, я обнаружил, что просто переупорядочив команды cout, значение «stuffed pec», которое является интересующим меня выводом, изменится .Читая в Интернете, я понял, что это может быть связано с неожиданным изменением стека памяти, что влияет на регистры результата, и что это может быть связано с операциями вне пределов других переменных.Я ошибаюсь в своем понимании?

Теперь я новичок, и это очень сложно.Возможно, я допустил несколько грубых ошибок, о которых мне ничего не известно, поэтому, пожалуйста, не стесняйтесь разрывать код на кусочки.Также, если это имеет значение, этот код выполняется на mbed LPC1768.

#include <iostream>


using namespace std;

unsigned short pec15Table[256];
const unsigned int CRC15_POLY = 0x4599;



void init_PEC15_Table() // Cyclical Redundancy Check lookup table generator function
{
    unsigned short rem;
    for (int i = 0; i < 256; i++)
    {
        rem = i << 7;
        for (int bit = 8; bit > 0; --bit)
        {
            if (rem & 0x4000)
            {
                rem = ((rem << 1));
                rem = (rem ^ CRC15_POLY);
            }
            else
            {
                rem = ((rem << 1));
            }
        }
        pec15Table[i] = rem & 0xFFFF;
//        cout << hex << pec15Table [i] << endl;
    }
}

 unsigned short pec15(char* data, int lengt = 16)  //Takes data as an input,
{
     int rem, address;
     rem = 16;//PEC seed (intial PEC value)
    for (int i = 0; i < lengt; i++)
    {
        address = ((rem >> 7) ^ data[i]) & 0xff;//calculate PEC table address
        rem = (rem << 8) ^ pec15Table[address];
    }
    return (rem * 2);//The CRC15 has a 0 in the LSB so the final value must be multiplied by 2
}

int main()
{
    init_PEC15_Table();         //initialise pec table
    char data = (short) 0x1 ;   // Write 0x1 to char array containing the data 0x1
    char* dataPtr = &data;      // Create a pointer to that array

    unsigned short result = pec15(dataPtr);                    //Pass data pointer to pec calculator


    cout << "data in: " << (short) *dataPtr << endl;        //Print the short representation of the char data array (Outputs 1)
    cout << "size of data: " << sizeof(*dataPtr) << endl;   //Print the size of the char array (Outputs 1)
    cout << "stuffed pec: " << result << endl;                 //Print the output of the pec calculation    

    return 0;
}

Ответы [ 2 ]

7 голосов
/ 20 июня 2019

Код, который вы написали здесь, не синхронизируется с комментариями, которые вы написали:

char data = (short) 0x1 ;   // Write 0x1 to char array containing the data 0x1
char* dataPtr = &data;      // Create a pointer to that array

Первая строка ничего не записывает в массив символов. Скорее, он создает переменную char, числовое значение которой равно 1. Как примечание, приведение к short здесь не требуется и не имеет никакого эффекта - вы хотели написать что-то еще?

Вторая строка не создает указатель на массив. Скорее, он создает указатель на переменную data. Вы можете думать об этом как о указателе на массив длины один, но это, вероятно, не то, что вы хотели сделать.

Две вышеприведенные строки сами по себе ничего плохого не делают. Следующая строка, однако, является реальной проблемой:

unsigned short result = pec15(dataPtr);                    //Pass data pointer to pec calculator

Помните, что pec15 имеет второй аргумент, который должен обозначать длину передаваемых данных. Поскольку вы не указали его, по умолчанию используется значение 16. Однако указатель dataPtr указывает только на один char значение, а не 16 char значения, поэтому это приводит к неопределенному поведению.

Я не уверен, как это исправить, потому что не понимаю смысла вашего кода. Вы хотели создать массив из 16 элементов? Вы имели в виду создать массив, заполненный значением 0x1? Правильное решение здесь зависит от ответа на этот вопрос.

4 голосов
/ 20 июня 2019

Попробуйте:

unsigned short result = pec15(dataPtr, 1);

в противном случае lengt равно 16 (имеет значение по умолчанию).Я бы также посоветовал удалить значение по умолчанию lengt, так как оно не имеет смысла в контексте функции pec15.

...