【问题标题】:HEAP error Invalid address specified to RtlValidateHeapHEAP 错误 指定给 RtlValidateHeap 的地址无效
【发布时间】:2015-11-10 00:40:03
【问题描述】:

我的记忆力有问题。我以这种方式使用结构:

Package.h 文件

#pragma once
#include <cstdlib>

struct Package {
    char *data;
    long long int *packageNumber;
    long long int *allPackages;

    Package(const int sizeOfData);
    ~Package();
};

包.cpp

#include "Package.h"

Package::Package(const int sizeOfData) {
    void *ptr = malloc(2 * sizeof(long long int) + sizeOfData * sizeof(char));
    packageNumber = (long long int*) ptr;
    allPackages = (long long int*) ((long long int*)ptr + sizeof(long long int));
    data = (char*)((char*)ptr + 2 * sizeof(long long int));
}

Package::~Package() {
    free(data);
    free(packageNumber);
    free(allPackages);
}

在方法中:

for (int j = 0; j < this->bufforSize || i * bufforSize + j < allPackages; j++) {
            Package package(this->packageSize);
            this->file->read(package.data, this->packageSize);
            *package.allPackages = allPackages;
            *package.packageNumber = i * this->bufforSize + j;
            this->dataPacked->push_back(package);
        }

在括号结束后抛出错误:"HEAP[zad2.exe]: Invalid address specified to RtlValidateHeap( 00000056FEFE0000, 00000056FEFF3B20 )" 我不知道我做错了什么。请帮忙,迈克尔。

编辑:现在它正在为循环的第一次迭代工作。帮助我将析构函数更改为:

Package::~Package() {
    free(packageNumber);
}

但是现在析构函数在循环的第二次迭代中对同一个结构对象执行了两次。

【问题讨论】:

  • 当您很明显使用 C++ 时,为什么要将此标记为 C。如果这个 C++,为什么不使用new [ ]delete[ ] 或者只是一个容器,比如std::vector
  • 你为什么要给free打3次电话?只有一个对malloc 的呼叫正在完成。
  • 因为我必须在连续的内存片段中进行。整个结构必须在一个地方。
  • 与使用 new char [ ]std::vector&lt;char&gt; 相比,malloc 没有任何魔力。它们基本上都做同样的事情,即以字节为单位分配一块连续的内存。至少与mallocstd::vector&lt;char&gt; 不同的是,您不再需要手动管理分配和解除分配,这就是您现在出现错误的原因。
  • @PaulMcKenzie 谢谢,但我想以 C 方式分配内存。例如,分配 n 大小的 char + m 大小 int 数组对我来说看起来更好。

标签: c++ memory-management struct memory-pool


【解决方案1】:

阅读freedescription

如果 ptr 的值不等于先前由 std::malloc()、std::calloc() 或 std::realloc() 返回的值,则行为未定义。

那就看看你的代码,注意我添加的cmets。

void *ptr = malloc(2 * sizeof(long long int) + sizeOfData * sizeof(char));
packageNumber = (long long int*) ptr; // you got this from malloc
allPackages = (long long int*) ((long long int*)ptr + sizeof(long long int)); // the value of this pointer is not equal to anything returned by malloc
data = (char*)((char*)ptr + 2 * sizeof(long long int)); // the value of this pointer is not equal to anything returned by malloc either

最后在析构函数中:

free(data); // was not allocated with malloc -> undefined behaviour
free(packageNumber); // was allocated with malloc -> OK
free(allPackages); // was not allocated with malloc -> undefined behaviour

您尝试删除不是从malloc 获得的指针。这会导致未定义的行为。该错误是由于未定义的行为。请注意free(packageNumber) 释放了用malloc 分配的整个内存块。这包括dataallPackages 指向的内存。

有一个简单的经验法则:每次调用 malloc/calloc 时,只调用一次 free。同样适用于delete+newdelete[]+new[]

【讨论】:

  • 很好的解释。它有帮助,但现在还有一个与此相关的错误。它出现在这之后。为什么我的程序在第二次循环中执行了第二次析构函数?
  • @PianistaMichal 您正在将对象复制到向量中。我敢打赌,你忘了遵守三法则,也没有实现正确的复制构造函数。
  • 矢量复制您的对象。由于您的Package 结构无法安全复制,因此通过将其放置在向量中,与复制Package 对象相关的所有错误都会暴露出来。如果您想将Package 对象存储在std::vector 等容器中,则需要通过实施规则3 来确保它是安全可复制的(因为您有指向动态分配内存的指针的成员)。
【解决方案2】:
allPackages = (long long int*) ((long long int*)ptr + sizeof(long long int));

当你使用一个 long long int 指针(在我们的例子中是被强制转换后的 ptr)并且你想要提前 sizeof(long long int) 字节,你只需要做 ptr++;

但我建议您重写代码并使用 3 个 malloc 而不是一个。

【讨论】:

  • 我建议不要写任何malloc 电话。只需将data 更改为std::vector&lt;char&gt;,即可获得相同的结果,而且无需管理任何内存。
猜你喜欢
  • 1970-01-01
  • 2015-10-15
  • 2016-07-13
  • 1970-01-01
  • 2020-05-04
  • 2020-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多