简体   繁体   中英

EXC_BAD_ACCESS error for std::string member of a structure

On accessing a struct member of type std::string, the error 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 行显示以下内容 .

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 , why am I unable to access it. 的存储区,但是为什么我无法访问它。 What am I missing. Please help.

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;

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

KeyValuePair temp; // Yes, that simple.

int main( ) {

    temp.value = "|";

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM