2

I'm not clear why this should fail, and why it fails where it does:

std::string* s;
s = (std::string*)malloc(sizeof(std::string) * 10);
s[0] = "string0";
s[1] = "string1";
s[2] = "string2"; //Segmentation fault

It doesn't matter what the size of strings assigned to s[0] - s[2] are, or how much space is malloc'ed. The same thing happens with QStrings. I presume that the trouble arises from the fact that std::string contains an internal pointer, so sizeof() just returns the size of the pointer, but given that std::strings behave like values otherwise (=, ==, etc.) I don't see why that entails failure here.

Also, for compatibility with other code I need to use C arrays here, not e.g. std::vector. And I'm looking for a general solution (that will work with QString, QDateTime, etc) if there is one. But I'd be happy just to know what's going on.

Edit: Got a downvote... What's wrong with this question? I did look around first for awhile (including SO), didn't find this addressed.

13
  • 1
    You really should use new (or new[] in this case) to dynamically allocate objects. And you can't tag this C as it is C++. Commented Aug 7, 2011 at 10:35
  • Yeah, std is not allowed in C. Commented Aug 7, 2011 at 10:36
  • @WTP Use new to dynamically allocate what exactly? Commented Aug 7, 2011 at 10:38
  • @Matt Phillips in this case std::string objects. Commented Aug 7, 2011 at 10:38
  • @WTP Fair enough that code is not C but it is the C way of representing and allocating an array, as opposed to e.g. std::vector. Commented Aug 7, 2011 at 10:40

6 Answers 6

10

You can not malloc an array of class objects, because this function does not invoke any constructors. You just get memory filled with garbage, which you then try to reinterpret as an array of class objects.

Arrays of C++ objects are allocated with new[].

As to compatibility with other code, you probably can use std::vector, because &vec[0] gives you a pointer to the first element in a contiguous array.


If you insist on using malloc and free, then you'll need to manually invoke the constructor for each array item with placement new and manually invoke each destructor before freeing.

Sign up to request clarification or add additional context in comments.

1 Comment

'because &vec[0] gives you a pointer to the first element in a contiguous array' - Not if the vector is zero size, unfortunately.
5

The problem is that std::string has a constructor that has to be called.

Not that having an array of strings is a good idea, but if you must:

string* s = new string[10];

Comments

3

The problem arises because you should not use malloc to allocate space for classes with constructors (like std::string) unless you really, really know what you are doing. Do it the easy way and use new

std::string* s;
s = new std::string[10];
s[0] = "string0";
s[1] = "string1";
s[2] = "string2";

The techinical reason for your code not working is that you haven't constructed any of your strings because you haven't called their constructors, all you've got is a block of uninitialised memory. On the other hand new does call the std::string constructor on the memory it allocates.

Comments

1

with malloc, the std::string's constructor is not called. That could be the reason. BTW, why are using malloc to allocate memory when you are using std::string ? What stops you in using new ?

3 Comments

I'm writing templated code I want to use with doubles, ints, etc. and for those I thought it would be most efficient to just use arrays. Didn't see this problem coming... :(
@Matt: In particular if you are using templates, then you can't normally use any of the un-type-aware C library functions.
@UncleBens Yes it looks like you nailed it, I'm going to give the thread a little more time to 'settle' then close it off.
1

As already mentioned:

You can not malloc an array of class objects, because this

function does not invoke any constructors. You just get memory filled with garbage, which you then try to reinterpret as an array of class objects.

If you want [ as a workaround ] do this:

char * s[10];

for (int i=0; i<10; i++) s[i] = new char[10];

strcpy(s[0], "string0");

strcpy(s[1], "string1");

strcpy(s[2], "string2");

Comments

0

What you probably want is a vector of strings:

std::vector<std::string> s(3);
s[0] = "string0";
s[1] = "string1";
s[2] = "string2";

Also, for compatibility with other code I need to use C arrays here, not e.g. std::vector

You can obtain a raw pointer to the first element for interop with legacy code:

string* p = &s[0];

1 Comment

He explicitly says, not std::vector.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.