Char *数据在访问时发生更改

时间:2018-06-24 17:18:38

标签: c++ arrays pointers memory

我正在开发具有功能的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 :(得分:1)

您正在返回一个指向本地数组的指针。 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版本可能会更快。

答案 1 :(得分:0)

您可以尝试使用report.data本身而不是buf。

val myDataReads = new Reads[MyData] {

//the JsValue passed to this reads should conform to structure expected by MyData
def reads(jsv:JsValue) = JsResult = {
//I want to pick each field, check its value and print error is something is wrong
  val uuidOptionReads:Reads[Option[UUID]] = (JsPath \ "field1").readNullable[UUID]; //not sure if this is correct
  //now I have got new Reads but how do I get uuid from here?
uuidOptionReads.reads(/*reads expects a JsValue but I don't know what to pass here.*/)
/*I want to repeat the above logic for other fields*/
}

  }