【问题标题】:Access Violation on char arraychar 数组的访问冲突
【发布时间】:2012-06-27 18:28:05
【问题描述】:

刚刚使用new创建的字符数组出现访问冲突。

DispatchCommand(char* cmdStr)
        {
            // Dispatch
            for(int i = 0; i < sizeof(_lpCommands); i++)
            {
                const int len = strlen(_lpCommands[i].szCommand);
                char* cmdblip = new char[len + 1];
                memcpy(&cmdblip, cmdStr, len);
                cmdblip[len] = '\0';  // Access Violation

                if(strcmp(cmdblip, _lpCommands[i].szCommand) == 0)
                {
                    if(strlen(cmdStr) > strlen(_lpCommands[i].szCommand))
                        (*_lpCommands[i].cbCallback)(&cmdStr[strlen(_lpCommands[i].szCommand)]);
                    else
                        (*_lpCommands[i].cbCallback)("");

                    delete cmdblip;
                    return;
                }

                delete cmdblip;
            }

            // Error and return
            *Out::ServerInfo<<"Command not found!"<<ENDL;
        }

_lpCommands 是 Command 结构的数组:

struct Command
{
    char* szCommand;
    CommandCallback cbCallback;
};

产生的错误信息是:

Program.exe 中 0x012219cf 处未处理的异常:0xC0000005:访问 违规写入位置0x66647366。

这是对使用 memcmp 的类似代码的重写,这最终也给了我访问冲突,而没有执行 memcpy

什么给了?

【问题讨论】:

  • 为什么不std::string?你在delete cmdblip; 中有未定义的行为。应该是delete [] cmdblip;
  • @FredLarson - 试图在程序的这个特定部分远离 std::string。并感谢您的提示!
  • 不要试图远离std::string,尽量远离char*
  • 不使用std::string 过于本地化。这段代码很糟糕,它出错的直接后果是您的代码非常糟糕,而不是任何特定的糟糕实例。
  • 正如标记的答案所述,我有一个错字并且正在将一个指针传递给一个指针。更改后我的代码完美运行。对于特定的代码部分,我需要远离std::string。给你的飞机降温,孩子们。

标签: c++ access-violation strcmp arrays


【解决方案1】:

不要将&amp;cmdblip 传递给memcpy。您应该传递一个指向目标缓冲区的指针,而不是指向该指针的指针。改为传递cmdblip

编辑:我同意一般来说,std::string 应该在 C++ 中使用。尽管如此,该代码崩溃的技术原因是memcpy 破坏了cmdblip 指针,使其指向实际上由复制字符串的前4 个字节组成的内存位置。然后,cmdblip[len] 导致内存位置不在分配的缓冲区(或任何其他合法分配的缓冲区)内,因此崩溃。因此,如果您想编写更好的代码,请使用 C++ 类。如果您想了解给定代码崩溃的原因,请考虑以上内容。

【讨论】:

  • @Di-0xide 你仍然需要将delete 更改为delete[],即使它似乎可以工作。
  • 是的,同时将cmdStr 参数的类型更改为const char*。您不会在代码中修改该字符串,因此请保护自己免受将来的意外修改。
  • @eran:是的。这个问题唯一可能的答案是“使用std::string”。您还不如给失业者提供一晚床来解决他们的问题 - 这并不是真正的解决方案根本
  • @DeadMG,请将您的鼠标放在您单击的那个小向下箭头上。它应该弹出一条消息说:“这个答案没有用”。我的回答绝对有用——它解决了有问题的问题。如果你想成为一个纯粹主义者,你可以就你自己的答案说出你的想法,就像你所做的那样。不要滥用投票 - 这个答案是完全正确的,即使它不会改变 OP 对 C++ 编程的一般方法。
  • @eran:你的回答没有有用。您所做的只是将 OP 的问题延迟了他必须维护该功能或编写新功能所需的时间。你什么都没解决。这里真正的问题是 OP 的代码很糟糕,这只是他经常遇到的 许多 错误之一,直到它被纠正为止。问题中的具体错误只是一个症状,纠正它并不能解决任何问题。
【解决方案2】:

对这个问题唯一可能有用的答案是“使用std::string”。每次您修改此函数或编写另一个类似的函数时,您现在遇到的特定问题只会再次出现或相同的问题。在一般情况下解决问题的唯一方法是转向基于类的解决方案,这是作为标准为您提供的。例如,您当前的代码是异常不安全的,除了任何给您带来访问冲突的东西之外,更不用说它不可读并乞求许多其他错误,例如一对一,不正确的 NULL 终止,双删除和内存泄漏。哦,还有 UB,因为你 delete 什么你 new[]

【讨论】:

  • @DomagojPandža - char* 是“真正的 C++”。我什至表示我想在这段特定的代码中避开字符串。我没有说我没有在其他任何地方使用字符串。
  • 这就留下了一个问题:为什么
  • @Di-0xide: char* 绝对不是 C++。
  • charpointers 什么时候不是 C++ 了? C 字符串 可能不是“C++”,但上次我检查了没有char 标量类型就不能拥有C++。
  • @DomagojPandža - 这很好,但我不是在这里获得使用 char 数组而不是 std::string 的选择的批准。我被告知我们需要将这部分代码保留为非std::string,这是有充分理由的。回答这个问题并提出一个善意的建议并不难,而不是似乎知道我个人是一个糟糕的程序员。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-16
  • 2013-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多