【问题标题】:EXC_BAD_ACCESS error for std::string member of a structure结构的 std::string 成员的 EXC_BAD_ACCESS 错误
【发布时间】:2014-07-01 08:17:50
【问题描述】:

在访问 std::string 类型的结构成员时,弹出错误 Bus Error: 10。代码如下。

#include <iostream>
#include <string>

struct KeyValuePair {
    std::string key;
    std::string value;
};

struct KeyValuePair *temp = (struct KeyValuePair *) malloc(sizeof(struct KeyValuePair));


int main(void) {

    temp->value = "|";

    temp->value += "someval|";

    std::cout << temp->value << std::endl;

    return 0;
}

在代码上运行 gdb 会在 temp->value = "|" 行显示以下内容。

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00007fff8d99e524
0x00007fff898dc7ca in std::string::_M_mutate ()

从上面的消息中,我了解到我的代码正在尝试访问无效/未经授权的内存区域。

我的问题:虽然我已经使用 malloc 来获取全局变量 temp 的内存区域,但为什么我无法访问它。我错过了什么。请帮忙。

【问题讨论】:

    标签: c++ c++11 malloc stdstring


    【解决方案1】:

    您需要使用new 而不是malloc 来确保构造std::string 对象。

    KeyValuePair *temp = new KeyValuePair;
    

    当你需要销毁结构体时,使用delete

    delete temp;
    

    作为一般经验法则,在 C++ 中编码时不应使用malloc。请改用new。正是因为这个原因。

    也就是说,对于您的简单示例,似乎没有真正需要动态分配。您可以避免这样的动态分配:

    KeyValuePair temp;
    

    【讨论】:

    • 为什么是new?没错,但初学者很少需要它。
    • @MSalters 确实如此。我只是想解释一下为什么malloc 是错误的。
    【解决方案2】:

    您在 C++ 中使用 C 构造。完全消除malloc

    KeyValuePair temp; // Yes, that simple.
    
    int main( ) {
    
        temp.value = "|";
    

    【讨论】:

      【解决方案3】:

      C和C++有区别:

      • 在 C 中,struct 的实例没有固有的不变量,它只是位于内存中
      • 在 C++ 中,structclass 的实例具有一组不变量,它们由构造函数建立并在其生命周期内由公共接口维护

      这里显示:

      • malloc,作为 C 构造,只会保留一些原始内存
      • new,作为 C++ 构造,不仅会保留一些原始内存,还会调用适当的构造函数,从而建立实例不变量(如果有)

      注意:如果将newint 等内置类型一起使用,new int 实际上不会初始化任何东西...

      因此,当访问temp-&gt;value 时,您访问的是未初始化的内存。这是未定义的行为(任何事情都可能发生),并且在您的情况下,程序遵循一些野指针并落在禁止访问的内存区域上。

      所以,暂时忘掉那些 C 主义吧:常规的 C++ 构造将确保为您正确调用构造函数。

      KeyValuePair temp;
      
      int main() {
          // ...
      }
      

      或者,如果你真的需要一个动态分配的值(有什么用?):

      KeyValuePair* temp = new KeyValuePair();
      
      int main() {
          // ...
      }
      

      但是你必须考虑在某个时候在temp 上调用delete,只调用一次,这要复杂得多。没有智能指针,这是一场失败的游戏。

      【讨论】:

      • 那是我的下一个任务。了解 malloc 和 new 之间的差异。你帮了我。
      猜你喜欢
      • 2023-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-27
      • 2017-02-25
      • 1970-01-01
      • 1970-01-01
      • 2014-11-23
      相关资源
      最近更新 更多