【问题标题】:C++ char array copy to unsigned char arrayC++ char 数组复制到 unsigned char 数组
【发布时间】:2012-04-15 15:37:33
【问题描述】:

我正在尝试读取文件并将信息存储在无符号字符数组中。但是,我的程序似乎覆盖了变量。

ClassA 标头:

...
public:
    ClassA(void);
    void LoadMemoryBlock(char* block, int bank);
....
private:
    unsigned char upperMemoryBank1[16384];
    unsigned char upperMemoryBank2[16384];
....

A 类文件:

ClassA::ClassA(void)
{
}
...
void ClassA::LoadMemoryBlock(char* block, int bank)
{
    if (bank == 1)
    {
        memcpy(upperMemoryBank1, block, 16384);
    }
    else if (bank == 2)
    {
        memcpy(upperMemoryBank2, block, 16384);
    }
}

B 类标头:

...
private:
    ClassA* classAobject;
...

B 类文件:

ClassB::ClassB()
{
    classAobject = &ClassA();
    ...
}
...
ClassB::StoreFile(ifstream &file)
{
    int position;

    char fileData[16384];

    position = file.tellg();
    file.seekg(HEADER_SIZE, ios::beg);
    position = file.tellg();
    file.read(fileData, 16384);
    position = file.tellg();
    classAobject->LoadMemoryBlock(fileData, 1);
    classAobject->LoadMemoryBlock(fileData, 2);

    position = file.tellg(); // Crashes here
    file.seekg(16384 + HEADER_SIZE, ios::beg);
    ...
}

在我的调试器中观察位置变量显示,在 LoadMemoryBlock 调用之后,它不再像之前那样显示 16400,而是每次都不同的随机数。此外,文件 ifstream 也被 LoadMemoryBlock 调用损坏。所以我猜测 memcpy 正在覆盖它们。

我尝试以不同的方式初始化我的数组,但现在 memcpy 崩溃了!

ClassA 标头:

...
public:
    ClassA(void);
    void LoadMemoryBlock(char* block, int bank);
....
private:
    unsigned char* upperMemoryBank1;
    unsigned char* upperMemoryBank2;
....

A 类文件:

ClassA::ClassA(void)
{
    upperMemoryBank1 = new unsigned char[16384];
    upperMemoryBank2 = new unsigned char[16384];
}
...
void ClassA::LoadMemoryBlock(char* block, int bank)
{
    if (bank == 1)
    {
        memcpy(upperMemoryBank1, block, 16384); // Crashes here
    }
    else if (bank == 2)
    {
        memcpy(upperMemoryBank2, block, 16384);
    }
}

B 类标头:

...
private:
    ClassA* classAobject;
...

B 类文件:

ClassB::ClassB()
{
    classAobject = &ClassA();
    ...
}
...
ClassB::StoreFile(ifstream &file)
{
    int position;

    char* fileData = new char[16384];

    position = file.tellg();
    file.seekg(HEADER_SIZE, ios::beg);
    position = file.tellg();
    file.read(fileData, 16384);
    position = file.tellg();
    classAobject->LoadMemoryBlock(fileData, 1);
    classAobject->LoadMemoryBlock(fileData, 2);

    position = file.tellg();
    file.seekg(16384 + HEADER_SIZE, ios::beg);
    ...
}

我认为这些方法中至少有一种(如果不是两种)应该有效。我做错了什么?

编辑:我已经包含了上面的 ClassA 初始化。

这就是我调用 StoreFile 方法的方式:

bool ClassB::Load(char* filename)
{
    ifstream file(filename, ios::in|ios::binary);

    if(file.is_open())
    {
        if(!StoreFile(file))
        {
            return false;
        }

        file.close();
        return true;
    }

    printf("Could not open file: %s\n", filename);
    return false;
}

【问题讨论】:

  • 请尝试做一个完整的例子,我们可以用它来重现问题。否则,我们只剩下猜测了。 (您可能会自己发现错误,同时将其缩小到这样的示例)
  • 为什么还有一个中间本地数组,而不是直接读入相关银行?
  • 您是否在该代码的开头检查了classAobject 指向ClassA 类的有效对象?

标签: c++ arrays char memcpy unsigned-char


【解决方案1】:

99% 的可能性是错误出现在初始化classAobject 指针值的任何代码中。如果它指向ClassA 对象的合法实例,则代码应该没问题。

更新:是的。就是这样。

classAobject = &ClassA();

这会创建一个新的 ClassA 对象,然后存储一个指向它的指针。但在语句结束时,它超出范围并被销毁,留下classAobject 持有指向不存在对象的指针。你想要:

classAobject = new ClassA();

不要忘记三个规则——delete 在析构函数中,在operator= 和复制构造函数中分配一个新的。或者更好的是,根据所需的语义使用更多的 C++ 方法,例如智能指针。

【讨论】:

  • 考虑“classAObject = new ClassA;” ...或者更好的是,只需将其设为静态并跳过新的。如果您坚持使用堆,请考虑 boost::shared_ptr 或其他托管容器以避免泄漏 RAM。
【解决方案2】:

ClassB 构造函数中,您正在初始化classAobject 指向临时变量地址的指针,该临时变量在构造函数返回后立即变为无效。这就是问题的原因。使用new 创建合适的堆对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    • 1970-01-01
    • 2011-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多