Данные Char * изменяются при доступе - PullRequest
0 голосов
/ 24 июня 2018

Я работаю над приложением c ++, которое имеет функцию

//ControllerCore.cpp
Report ControllerCore::GetReport() {
unsigned char buf[256];
int res = 0;
while (res == 0) {
    res = get_unsigned_char*(buf, sizeof(buf));
    if (res < 0)
        printf("Unable to read()\n");
#ifdef WIN32
    Sleep(50);
#else
    usleep(50 * 1000);
#endif

}

Report report = Report();
report.data = buf;
report.dataLength = res;
return report;
}

Отчет определяется как

//Report.h
struct Report
{
    public:
        unsigned char* data;
        int dataLength;
};

Когда ContollerCore :: GetReport () возвращает, он присваивает report.data указателю на массив беззнаковых символов, с которым я могу работать отлично. Но когда вызывающая сторона пытается напечатать report.data, значения массива изменяются.

//Main.cpp
int RequestReport() {

    Report report = core.GetReport();
    for (int i = 0; i < report.dataLength; i++) {
        std::cout << "0x" << std::hex << (int)report.data[i] << ", ";
    }
    std::cout << std::endl;
    return 1;
}

Ответы [ 2 ]

0 голосов
/ 24 июня 2018

Вы возвращаете указатель на локальный массив. Как только ControlerCore::GetReport возвращается, buf выходит из области видимости и уничтожается. Любая попытка получить к нему доступ после этого приводит к неопределенному поведению.

Вам нужно заставить Report фактически хранить данные напрямую. Самый простой способ - использовать std::vector:

struct Report
{
    std::vector<unsigned char> data;
    // don't need dataLength anymore since std::vector knows its size
};

Report ControllerCore::GetReport() {
    Report report;
    report.data.resize(256);
    int res = 0;
    while (res == 0) {
        res = get_data(report.data.data(), report.data.size());
    }
    report.data.resize(res);
    return report;
}

Теперь, когда Report имеет только одного члена, он, вероятно, больше не нужен, и вы можете просто вместо этого вернуть std::vector<unsigned char>.

Если вы хотите избежать динамического выделения, используемого std::vector, вы можете вместо этого использовать std::array (или необработанный массив):

struct Report
{
    std::array<unsigned char, 256> data;
    size_t dataLength; // back now, since the length of the data won't match the size of the contianer
};

Report ControllerCore::GetReport() {
    Report report;
    int res = 0;
    while (res == 0) {
        res = get_data(report.data.data(), report.data.size());
    }
    report.dataLength = res;
    return report;
}

Это позволяет избежать динамического выделения, но требует дополнительной копии данных, поскольку std::array не может быть эффективно перемещен, как std::vector. Это означает, что если динамическое распределение не будет особенно медленным на вашей платформе, версия std::vector, вероятно, будет быстрее.

0 голосов
/ 24 июня 2018

Вы можете попробовать использовать сам report.data вместо buf. * ​​1001 *

Report ControllerCore::GetReport() {
Report report;
report.data=new char[256];
int res = 0;
while (res == 0) {
    res = get_unsigned_char*(report.data, sizeof(char)*256);
    if (res < 0)
        printf("Unable to read()\n");
#ifdef WIN32
    Sleep(50);
#else
    usleep(50 * 1000);
#endif

}

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