EXC_BAD_ACCESS error for std::string member of a structure

一世执手 提交于 2021-02-08 09:39:13

问题


On accessing a struct member of type std::string, the error Bus Error: 10 popped up. Code is as following.

#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;
}

Running gdb on the code shows the following at the line 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 ()

From above message all I understand is that my code is trying to access an invalid/unauthorized memory area.

My question: Though I have used malloc to obtain a memory area for the global variable temp, why am I unable to access it. What am I missing. Please help.


回答1:


There is a difference between C and C++:

  • in C, an instance of a struct has no inherent invariant, it just sits in memory
  • in C++, an instance of a struct or class has a set of invariants that are established by the constructor and maintained by the public interface throughout its lifetime

This shows up here:

  • malloc, being a C construct, will just reserve some raw memory
  • new, being a C++ construct, will not only reserve some raw memory, but also call the appropriate constructor and thus establish the instance invariants (if any)

Note: if using new with built-in types such as int, new int does not actually initialize anything...

Therefore, when accessing temp->value, you are accessing uninitialized memory. This is Undefined Behavior (anything may happen), and, in your case, the program follows some wild pointer and lands on a memory zone it is forbidden to access.

So, just forget about those C-isms for now: regular C++ constructs will ensure the constructor is appropriately called for you.

KeyValuePair temp;

int main() {
    // ...
}

Or, if you really need a dynamically allocated value (what for ?):

KeyValuePair* temp = new KeyValuePair();

int main() {
    // ...
}

But then you have to think about calling delete on temp at some point, only once, which is much more complicated. Without a smart pointer, it is a losing game.




回答2:


You need to use new rather than malloc to ensure that the std::string objects are constructed.

KeyValuePair *temp = new KeyValuePair;

When you need to destroy the struct, use delete.

delete temp;

As a general rule of thumb, you should not be using malloc when coding in C++. Use new instead. For this very reason.

That said, for your simple example, there seems no real need to allocate dynamically. You could avoid dynamic allocation like this:

KeyValuePair temp;



回答3:


You're using C constructs in C++. Just eliminate malloc entirely:

KeyValuePair temp; // Yes, that simple.

int main( ) {

    temp.value = "|";


来源:https://stackoverflow.com/questions/24505487/exc-bad-access-error-for-stdstring-member-of-a-structure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!