问题
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
orclass
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 memorynew
, 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