How to test for vector initialization success/failure in C++ - c++

I have a C++ class with vector<float> members which are initialized in the constructor to a size determined by one of the constructor's arguments.
summingBuffer = vector<float>(requiredSize);
How do I check whether the vector constructor has successfully allocated the the required space? The instance vars aren't pointers (should they be?) so if (NULL==myVector) doesn't work. Does vector throw an exception on allocation error? How about checking .size() afterwards?
Thank you...

Default allocator throws std::bad_alloc on failed allocation, just like new T does. So, no, no size checking is necessary. This isn't C.

The vector constructor will raise bad_alloc if it couldn't allocate enough storage, no need for extra checks.
Using pointers is not a good idea if you don't absolutely need them.
Also, looks like you could initialize your vectors directly rather than how you're doing it by using your constructor's initializer list. Something like:
struct foo {
std::vector<float> things;
foo(int vsize) : things(vsize) {
// rest of constructor code
}
};

Related

How to initialize non-POD data in malloc memory

I have a structure which has an std::list as its data member. That std::list is an collection of std::pair.
Like this(Inside .h file)
extern struct_info tt;
typedef struct_s *struct_info;
typedef
struct struct_s {
std::list < std::pair <char*, int> > names;
};
I am allocating memory for this structure in my .cpp file as:
tt = mem_malloc(sizeof(struct_t));
mem_malloc is my own memory allocating routine. Please note that it is already made extern in .h file.
Later, when I try to push_back any element into the list with following code:
std::pair <char*, int> myPair = std:make_pair("A", 5);
(tt->names).push_back(myPair);
It crashes while doing push_back. I do not know what is happening here. Do I need to call any constructor or initializer for the list in struct_s constructor?
What do you guys think?
You can't just allocate memory with size sizeof(struct_t) and expect to be able to use that memory as if a struct_t instance existed there - you need to construct it first. E.g.
tt = mem_malloc(sizeof(struct_t));
new (tt) struct_s{}; // <- "placement `new`"
// use `tt`...
tt->~struct_s(); // <- explicit destructor call
// deallocate tt
This is however a terrible idea, especially if done manually. The Standard Library provides allocator support - you should create an allocator that can be seamlessly used with the Standard Library instead.
You can also do:
struct_s obj;
*tt = obj;
.
.
.
free(tt);
After experiments:
1. With non POD types my suggested solution will (must) not work.
2. For non POD types if above copy mechanism is applied, it will start accessing uninitialised memory location (in copy-to-location), assuming as if those are well-formed objects, and therefore will cause segmentation fault.
3. Point 2 makes it compulsory to initialize such malloced memory for non-POD types data properly. This in C is not possible and we will also not encounter such scenario there as there is everything is POD. This is the reason (I think, one of the reasons) C++ struct is made very similar to Class, so that, as suggested in other solutions, we can make appropriate initialization calls (i.e. constructors).
So the solution is to use placement new operator as suggested by others.

Make Boost Matrix attribute of a class

I want to make a Boost Matrix as an attribute of my class Adsorbate. I know beforehand that it will be (3,2). I want to do:
#include <boost/numeric/ublas/matrix.hpp>
using namespace boost::numeric::ublas;
class Adsorbate {
matrix<double> m(3,2);
};
so that the compiler knows the size of the attribute m and thus my class Adsorbate. This way, I can make a pointer array of 200 of them:
Adsorbate * adsorbates = (Adsorbate *) malloc(200 * sizeof(Adsorbate));
How can I do this?
With regards to how to create an array of matrices, you are asking how to create a C array for a C++ data structure. Calling malloc will not correctly initialize the matrices in the array, nor calling "free" will deallocate dynamic memory if instances of ublas::matrix uses it, both failure to initialize an instance and failure to destroy it are severe bugs because things might seem to work, depending on the contents of the raw memory it can be all zeroes or something the application can handle, but it can also be be garbage that lead to catastrophic failures. Malloc will only give back the memory for instances, but internally, an instance of Adsorbate which has an instance of ublas::matrix might think it has valid pointers to memory or whatever.
To properly initialize the individual members of the array, Adsorbate *adsorbates = new Adsorbate[200];
Will use the default constructor for all the Adsorbate instances.
You can make it so that the default constructor of Adsorbate constructs its member m with 3,2:
struct Adsorbate {
Adsorbate(): m{3, 2}, ... orther instance initializations here ... { ...arbitrary constructor code here.... }
...
}
Arrays are not advised. The advised way is to create an std::vector<Adsorbate>. It might seem more complicated to use std::vector but it isn't, it will keep you from doing apparently simpler things that are potentially catastrophic unbeknownst to you.
If you insist on using naked arrays make sure to delete[] an array instead of delete. The difference is that delete calls only the destructor of one element.
Just initialize it in the constructor:
class Adsorbate {
private:
matrix<double> m;
public:
Adsorbate() : m(3, 2) {}
// ...
};
Also if you want to create an array of 200 Adsorbate, use std::vector:
std::vector<Adsorbate> adsorbates(200);

How do I initialize a vector member of a struct?

Suppose I have a struct with a member that is a vector. In the constructor, I want to just set it to NULL. But then later I want to be able to push_back things to it. How do I initialize the vector after it's NULL?
struct structName {
vector<int> vec;
structName() {
vec = NULL
}
void set(int);
}
void structName::set(int n) {
// What do I put here?
vec.push_back(n);
}
Thanks for the help!
It's already initialized via the default constructor and, if you need to call a different constructor, use an initialization list.
Remember, this is C++, not Java/C#/whatever. It makes no sense for an object to be null (ok, it doesn't in those languages either, but read on). It can't happen. In Java and languages like it you have variables which are references to objects and those references (not objects!) may or may not be null.
That is not the case in C++. There is a strict delineation between objects and pointers which refer to them (and pointers, or course, can be null or refer to an invalid memory location).
The default constructor for the vector will set it to its simplest state: no contents. So just leave it alone.
I think you be thinking of C++ objects like you would in Java. DON'T They are totally different beasts.
In C++, objects aren't references as in Java, thus, nulling them out doesn't make sense. In fact trying vec = NULL is an error as NULL is really just 0.
Instead just remove the line vec = NULL and it'll work as is. The vector will be default constructed as empty and you don't have to do any other initialization.
Initializing a vector to NULL doesn't make any sense. Perhaps you're getting confused with pointers. If you want to initialize your vector to the empty vector then that happens automatically. Like this in other words
struct structName {
vector<int> vec;
structName() {
}
void set(int);
}
void structName::set(int n) {
vec.push_back(n);
}

C++ New vs Malloc for dynamic memory array of Objects

I have a class Bullet that takes several arguments for its construction. However, I am using a dynamic memory array to store them. I am using C++ so i want to conform to it's standard by using the new operator to allocate the memory. The problem is that the new operator is asking for the constructor arguments when I'm allocating the array, which I don't have at that time. I can accomplish this using malloc to get the right size then fill in form there, but that's not what i want to use :) any ideas?
pBulletArray = (Bullet*) malloc(iBulletArraySize * sizeof(Bullet)); // Works
pBulletArray = new Bullet[iBulletArraySize]; // Requires constructor arguments
Thanks.
You can't.
And if you truly want to conform to C++ standards, you should use std::vector.
FYI, it would probably be even more expensive than what you're trying to achieve. If you could do this, new would call a constructor. But since you'll modify the object later on anyway, the initial construction is useless.
1) std::vector
A std::vector really is the proper C++ way to do this.
std::vector<Bullet> bullets;
bullets.reserve(10); // allocate memory for bullets without constructing any
bullets.push_back(Bullet(10.2,"Bang")); // put a Bullet in the vector.
bullets.emplace_back(10.2,"Bang"); // (C++11 only) construct a Bullet in the vector without copying.
2) new [] operator
It is also possible to do this with new, but you really shouldn't. Manually managing resources with new/delete is an advanced task, similar to template meta-programming in that it's best left to library builders, who'll use these features to build efficient, high level libraries for you. In fact to do this correctly you'll basically be implementing the internals of std::vector.
When you use the new operator to allocate an array, every element in the array is default initialized. Your code could work if you added a default constructor to Bullet:
class Bullet {
public:
Bullet() {} // default constructor
Bullet(double,std::string const &) {}
};
std::unique_ptr<Bullet[]> b = new Bullet[10]; // default construct 10 bullets
Then, when you have the real data for a Bullet you can assign it to one of the elements of the array:
b[3] = Bullet(20.3,"Bang");
Note the use of unique_ptr to ensure that proper clean-up occurs, and that it's exception safe. Doing these things manually is difficult and error prone.
3) operator new
The new operator initializes its objects in addition to allocating space for them. If you want to simply allocate space, you can use operator new.
std::unique_ptr<Bullet,void(*)(Bullet*)> bullets(
static_cast<Bullet*>(::operator new(10 * sizeof(Bullet))),
[](Bullet *b){::operator delete(b);});
(Note that the unique_ptr ensures that the storage will be deallocated but no more. Specifically, if we construct any objects in this storage we have to manually destruct them and do so in an exception safe way.)
bullets now points to storage sufficient for an array of Bullets. You can construct an array in this storage:
new (bullets.get()) Bullet[10];
However the array construction again uses default initialization for each element, which we're trying to avoid.
AFAIK C++ doesn't specify any well defined method of constructing an array without constructing the elements. I imagine this is largely because doing so would be a no-op for most (all?) C++ implementations. So while the following is technically undefined, in practice it's pretty well defined.
bool constructed[10] = {}; // a place to mark which elements are constructed
// construct some elements of the array
for(int i=0;i<10;i+=2) {
try {
// pretend bullets points to the first element of a valid array. Otherwise 'bullets.get()+i' is undefined
new (bullets.get()+i) Bullet(10.2,"Bang");
constructed = true;
} catch(...) {}
}
That will construct elements of the array without using the default constructor. You don't have to construct every element, just the ones you want to use. However when destroying the elements you have to remember to destroy only the elements that were constructed.
// destruct the elements of the array that we constructed before
for(int i=0;i<10;++i) {
if(constructed[i]) {
bullets[i].~Bullet();
}
}
// unique_ptr destructor will take care of deallocating the storage
The above is a pretty simple case. Making non-trivial uses of this method exception safe without wrapping it all up in a class is more difficult. Wrapping it up in a class basically amounts to implementing std::vector.
4) std::vector
So just use std::vector.
It's possible to do what you want -- search for "operator new" if you really want to know how. But it's almost certainly a bad idea. Instead, use std::vector, which will take care of all the annoying details for you. You can use std::vector::reserve to allocate all the memory you'll use ahead of time.
Bullet** pBulletArray = new Bullet*[iBulletArraySize];
Then populate pBulletArray:
for(int i = 0; i < iBulletArraySize; i++)
{
pBulletArray[i] = new Bullet(arg0, arg1);
}
Just don't forget to free the memory using delete afterwards.
The way C++ new normally works is allocating the memory for the class instance and then calling the constructor for that instance. You basically have already allocated the memory for your instances.
You can call only the constructor for the first instance like this:
new((void*)pBulletArray) Bullet(int foo);
Calling the constructor of the second one would look like this (and so on)
new((void*)pBulletArray+1) Bullet(int bar);
if the Bullet constructor takes an int.
If what you're really after here is just fast allocation/deallocation, then you should look into "memory pools." I'd recommend using boost's implementation, rather than trying to roll your own. In particular, you would probably want to use an "object_pool".

Erase all members of a class

Yesterday I read some code of a colleague and came across this:
class a_class
{
public:
a_class() {...}
int some_method(int some_param) {...}
int value_1;
int value_2;
float value_3;
std::vector<some_other_class*> even_more_values;
/* and so on */
}
a_class a_instances[10];
void some_function()
{
do_stuff();
do_more_stuff();
memset(a_instances, 0, 10 * sizeof(a_class)); // <===== WTF?
}
Is that legal (the WTF line, not the public attributes)? To me it smells really, really bad...
The code ran fine when compiled with VC8, but it throws an "unexpected exception" when compiled with VC9 when calling a_instances[0].event_more_values.push_back(whatever), but when accessing any of the other members. Any insights?
EDIT: Changed the memset from memset(&a_instances... to memset(a_instances.... Thanks for pointing it out Eduard.
EDIT2: Removed the ctor's return type. Thanks litb.
Conclusion: Thanks folks, you confirmed my suspicion.
This is a widely accepted method for initialization for C structs.
In C++ it doesn't work ofcourse because you can't assume anything about vectors internal structure. Zeroing it out is very likely to leave it in an illegal state which is why your program crashes.
He uses memset on a non-POD class type. It's invalid, because C++ only allows it for the simplest cases: Where a class doesn't have a user declared constructor, destructor, no virtual functions and several more restrictions. An array of objects of it won't change that fact.
If he removes the vector he is fine with using memset on it though. One note though. Even if it isn't C++, it might still be valid for his compiler - because if the Standard says something has undefined behavior, implementations can do everything they want - including blessing such behavior and saying what happens. In his case, what happens is probably that you apply memset on it, and it would silently clear out any members of the vector. Possible pointers in it, that would point to the allocated memory, will now just contain zero, without it knowing that.
You can recommend him to clear it out using something like this:
...
for(size_t i=0; i < 10; i++)
objects[i].clear();
And write clear using something like:
void clear() {
a_object o;
o.swap(*this);
}
Swapping would just swap the vector of o with the one of *this, and clear out the other variables. Swapping a vector is especially cheap. He of course needs to write a swap function then, that swaps the vector (even_more_values.swap(that.even_more_values)) and the other variables.
I am not sure, but I think the memset would erase internal data of the vector.
When zeroing out a_instances, you also zero out the std_vector within. Which probably allocates a buffer when constructed. Now, when you try to push_back, it sees the pointer to the buffer being NULL (or some other internal member) so it throws an exception.
It's not legitimate if you ask. That's because you can't overload writing via pointers as you can overload assignment operators.
The worst part of it is that if the vector had anything in it, that memory is now lost because the constructor wasn't called.
NEVER over-write a C++ object. EVER. If it was a derived object (and I don't know the specifics of std::vector), this code also over-writes the object's vtable making it crashy as well as corrupted.
Whoever wrote this doesn't understand what objects are and needs you to explain what they are and how they work so that they don't make this kind of mistake in the future.
You shouldn't do memset on C++ objects, because it doesn't call the proper constructor or destructor.
Specifically in this case, the destructor of even_more_values member of all a_instances's elements is not called.
Actually, at least with the members that you listed (before /* and so on */), you don't need to call memset or create any special destructor or clear() function. All these members are deleted automatically by the default destructor.
You should implement a method 'clear' in your class
void clear()
{
value1=0;
value2=0;
value_3=0f;
even_more_values.clear();
}
What you have here might not crash, but it probably won't do what you want either! Zeroing out the vector won't call the destructor for each a_class instance. It will also overwrite the internal data for a_class.even_more_values (so if your push_back() is after the memset() you are likely to get an access violation).
I would do two things differently:
Use std::vector for your storage both in a_class and in some_function().
Write a destructor for a_class that cleans up properly
If you do this, the storage will be managed for you by the compiler automatically.
For instance:
class a_class
{
public:
a_class() {...}
~a_class() { /* make sure that even_more_values gets cleaned up properly */ }
int some_method(int some_param) {...}
int value_1;
int value_2;
float value_3;
std::vector<some_other_class*> even_more_values;
/* and so on */
}
void some_function()
{
std::vector<a_class> a_instances( 10 );
// Pass a_instances into these functions by reference rather than by using
// a global. This is re-entrant and more likely to be thread-safe.
do_stuff( a_instances );
do_more_stuff( a_instances );
// a_instances will be cleaned up automatically here. This also allows you some
// weak exception safety.
}
Remember that if even_more_values contains pointers to other objects, you will need to delete those objects in the destructor of a_class. If possible, even_more_values should contain the objects themselves rather than pointers to those objects (that way you may not have to write a destructor for a_class, the one the compiler provides for you may be sufficient).