结构体的std::string成员的EXC_BAD_ACCESS错误

EXC_BAD_ACCESS error for std::string member of a structure

本文关键字:BAD 错误 ACCESS 成员 std string 结构体 EXC      更新时间:2023-10-16

访问std::string类型的struct成员时,弹出错误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的内存区域,为什么我无法访问它。我错过了什么?请帮助。

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

KeyValuePair *temp = new KeyValuePair;

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

delete temp;

作为一般的经验法则,在c++中编码时不应该使用malloc。使用new代替。

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

KeyValuePair temp;

您在c++中使用C结构。完全消除malloc:

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

C和c++的区别:

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

显示在这里:

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

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

因此,当访问temp->value时,您访问的是未初始化的内存。这是未定义的行为(任何事情都可能发生),在您的情况下,程序跟随某个野指针并落在禁止访问的内存区域。

所以,现在就忘掉那些C-isms:常规的c++构造将确保构造函数被适当地调用。

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

或者,如果您确实需要动态分配的值(为什么?):

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

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