【问题标题】:AccessViolationException on a deleted array已删除数组上的 AccessViolationException
【发布时间】:2013-02-19 13:25:08
【问题描述】:
static void InvShiftRows(BYTE* dest)
{
    tcout << "\t\t\tInvShiftRows()+" << EOL;
    BYTE* temp = new BYTE[16];
    ByteUtil::LogArray("temp1", temp, 16);
    memcpy(temp, dest, 16);
    ByteUtil::LogArray("temp2", temp, 16);
    dest[0x01] = temp[0x0D];
    dest[0x02] = temp[0x0A];
    dest[0x03] = temp[0x07];
    dest[0x05] = temp[0x01];
    dest[0x06] = temp[0x0E];
    dest[0x07] = temp[0x0B];
    dest[0x09] = temp[0x05];
    dest[0x0A] = temp[0x02];
    dest[0x0B] = temp[0x0F];
    dest[0x0D] = temp[0x09];
    dest[0x0E] = temp[0x06];
    dest[0x0F] = temp[0x03];
    ByteUtil::LogArray("Dest1", dest, 16);
    delete[] temp;
    tcout << "\t\t\tInvShiftRows()-" << EOL;
}

所以我发现访问冲突偶尔会发生在delete[] temp 上,而对于我来说,我无法弄清楚为什么。它只是随机执行。有什么线索吗?

编辑 每个请求查看 ByteUtil::LogArray

void ByteUtil::LogArray(char* header, const BYTE* thearray, int length)
{
    tcout << header << "(" << length << ")-";

    char* number = new char[4];
    for(int i=0; i<length; i++)
    {
        sprintf_s(number, 4,"%02X:", thearray[i]);
        wcout << number;
    }
    delete[] number;
    wcout << EOL; //EOL is just std::endl << std::flush
}

老实说,我认为我用 delete[] 做了一些坏动作。我在我的一篇代码审查帖子中了解到,每当我使用 new X[] 时,我都应该使用 delete[],所以我开始将它们放在我有类似 BYTE temp[4] 的任何地方,我将用 BYTE* temp = new BYTE[4] 替换并添加相应的 delete[ ]。起初似乎如果我使用 new X[] 它将将该数组中的所有值设置为零(结果证明是虚假的,因为它正在抛弃我的加密/解密方法)所以现在我正在尝试找出我的哪个删除删除太多...这让我想问另一个问题..

在方法中使用BYTE temp[4] = {0x00}; 是不负责任的吗?还是使用new X[]delete[] 更好?

【问题讨论】:

  • 内存在删除时已经损坏。你应该在不同的地方寻找问题。
  • 是的...试图找到那是我肉体上的一根刺。这可以解释为什么它是随机的......有时是这个功能,有时是其他功能......而且从来没有在同一个地方......这真的让我发疯......
  • ByteUtil::LogArray 有可能这样做吗?你能告诉我们它的代码吗?
  • 我会在一秒钟内展示它..我承认它似乎在其他地方......我无法弄清楚..我真的需要花一些时间在指针上并更好地学习它们,但不幸的是,这个特定的项目是按时完成的。 :/ 这段代码并不总是罪魁祸首..似乎在任何有 delete[] 方法的地方。呃..
  • @Robert Snyder BYTE temp[4] = {0x00} 没问题。更好的做法可能是使用 std::vector 或 std::array。

标签: visual-c++ access-violation


【解决方案1】:

如果问题与堆损坏有关,您可以包含&lt;crtdbg.h&gt; 并为每个 alloc/dealloc 打开堆检查:

在应用程序开头的某处运行:

// _CRTDBG_ALLOC_MEM_DF -- Turn on debug allocation
// _CRTDBG_CHECK_ALWAYS_DF -- check the heap's integrity at every allocation and deallocation.
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF);

如果问题与堆相关,您将收到一个断言(调试断言失败!表达式:_CrtCheckMemory())。在此之后追溯程序执行并寻找堆损坏的地方。

例如如果你在上面的代码中添加dest[0x10] = temp[0x03]; 并且 dest 在堆上分配,你会在 cout 的 LogArray 中得到一个断言。

注意:设置 _CRTDBG_CHECK_ALWAYS_DF 可能会使您的应用运行缓慢。

【讨论】:

  • 这就是我喜欢这个地方的原因。谢谢你的建议。我迫不及待想试一试。我不介意它很慢,只要我可以追踪它并找到它..让你的程序崩溃 100 次才能让它工作一次真是令人沮丧......这可能是一个愚蠢的问题,但我的构建必须处于调试模式?
  • @Robert Snyder 是的,当未定义 _DEBUG 时,在预处理期间会删除对 _CrtSetDbgFlag 的调用。
  • 这个我的朋友我是一个完美的解决方案,而不是因为我的版本不能是调试版本。哈!谢谢.. 今天早上我决定看看我是否可以通过摆脱所有 delete[] 来解决我的问题,它似乎减慢了它的速度......这对我来说意味着我使用的比我分配的要多,现在打开这个调试技巧并检查一下。项目是 OPOS 的 COM 库会不会有什么坏处?
  • @Robert Snyder _CrtSetDbgFlag 不应在生产中使用。它非常适合调试目的。是的,使用 std::vector 或 std::array 代替 new[] 和 delete[] 可能会更好。我不知道要求,但是在 OPOS 的 COM 库中使用 std::vector 应该没有问题。
猜你喜欢
  • 2022-07-22
  • 1970-01-01
  • 1970-01-01
  • 2019-11-26
  • 2017-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-11
相关资源
最近更新 更多