Proper way to create unique_ptr that holds an allocated array - c++

What is the proper way to create an unique_ptr that holds an array that is allocated on the free store? Visual studio 2013 supports this by default, but when I use gcc version 4.8.1 on Ubuntu I get memory leaks and undefined behaviour.
The problem can be reproduced with this code:
#include <memory>
#include <string.h>
using namespace std;
int main()
{
unique_ptr<unsigned char> testData(new unsigned char[16000]());
memset(testData.get(),0x12,0);
return 0;
}
Valgrind will give this output:
==3894== 1 errors in context 1 of 1:
==3894== Mismatched free() / delete / delete []
==3894== at 0x4C2BADC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3894== by 0x400AEF: std::default_delete<unsigned char>::operator()(unsigned char*) const (unique_ptr.h:67)
==3894== by 0x4009D0: std::unique_ptr<unsigned char, std::default_delete<unsigned char> >::~unique_ptr() (unique_ptr.h:184)
==3894== by 0x4007A9: main (test.cpp:19)
==3894== Address 0x5a1a040 is 0 bytes inside a block of size 16,000 alloc'd
==3894== at 0x4C2AFE7: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3894== by 0x40075F: main (test.cpp:15)

Using the T[] specialisation:
std::unique_ptr<unsigned char[]> testData(new unsigned char[16000]());
Note that, in an ideal world, you would not have to explicitly use new to instantiate a unique_ptr, avoiding a potential exception safety pitfall. To this end, C++14 provides you with the std::make_unique function template. See this excellent GOTW for more details. The syntax is:
auto testData = std::make_unique<unsigned char[]>(16000);

Use the array version :
auto testData = std::unique_ptr<unsigned char[]>{ new unsigned char[16000] };
Or with c++14, a better form ( VS2013 already has it ):
auto testData = std::make_unique<unsigned char[]>( 16000 );

A most likely better way would be to use std::vector<unsigned char> instead
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<unsigned char> testData(0x12, 0); // replaces your memset
// bla
}
The advantage is that this is much less error-prone and gives you access to all kinds of features such as easy iteration, insertion, automatic reallocation when capacity has been reached.
There is one caveat: if you are moving your data around a lot, a std::vector costs a little more because it keeps track of the size and capacity as well, rather than only the beginning of the data.
Note: your memset doesn't do anything because you call it with a zero count argument.

unsigned int size=16000;
std::unique_ptr<unsigned char[], std::default_delete<unsigned char[]>> pData(new unsigned char[size]);

Seems like a goofup, i will explain what i mean
class Object {
private :
static int count;
public :
Object() {
cout << "Object Initialized " << endl;
count++;
}
~Object() {
cout << "Object destroyed " << endl;
}
int print()
{
cout << "Printing" << endl;
return count;
}
};
int Object::count = 0;
int main(int argc,char** argv)
{
// This will create a pointer of Object
unique_ptr<Object> up2 = make_unique<Object>();
up2->print();
// This will create a pointer to array of Objects, The below two are same.
unique_ptr<Object[]> up1 = std::make_unique<Object[]>(30);
Object obj[30];
cout << up1.get()[8].print();
cout << obj[8].print();
// this will create a array of pointers to obj.
unique_ptr<Object*[]> up= std::make_unique<Object*[]>(30);
up.get()[5] = new Object();
unique_ptr<Object> mk = make_unique<Object>(*up.get()[5]);
cout << up.get()[5]->print();
unique_ptr<unique_ptr<Object>[]> up3 = std::make_unique<unique_ptr<Object>[]>(20);
up3.get()[5] = make_unique<Object>();
return 0;
}
Objective of the post is that there are hidden small subtle things you need to understand. Creating array of objects is same as object array of unique_ptr. It will make difference only when you pass it in the argument. Creating array of object pointers of unique_ptr is also not very useful. So only below two you need to use in most scenarios.
unique_ptr<Object> obj;
//and
unique_ptr<unique_ptr<Object>[]>= make_unique<unique_ptr<Object>[]>(20);

Probably something like the following?
using namespace std;
int size = get_size();
int const init_value = 123;
unique_ptr<int[]> p = make_unique<int[]>(size)
fill(p.get(), p.get() + size, init_value);

Related

Initializing a Struct's variable const char* const* with C++

I am trying to solve a coding question that requires the results be returned using a given struct. The struct is defined as:
struct Answer
{
const char* const* lastNames;
unsigned numberOfPeople;
}
Where the lastNames is a pointer to last names that are each terminated by a non-alpha char. I can not seem to find any way to convert the vector of strings that I am using to compile all the last names into a variable that I can assign to lastNames. I have tried making a single string with all the last names and assigning it with c_str() like so:
Ans->lastName = allNames.c_str(); but this gives me an error. Due to the limitations of the question I am unable to change the struct variable to anything else. How can I assign a string to a const char* const*
The structure being used effectively uses a C-style approach to defining a variable sized array of pointers to char (with const sprinkled over it). You’ll need storage for both the array of char const* as well as the entities pointed to. Here is how you could build it from a std::vector<std::string>:
std::vector<std::string> strings = somehow_compute_the_strings();
std::vector<char const*> array;
for (std::string const& s: strings) {
array.push_back(s.c_str());
}
Answer answer = { array.data(), array.size() };
Of course, you can’t return answer without the pointer inside pointing to stale data: you’d need to keep the two std::vectors alive. Potentially these two objects could be made members of an object the function is called on. To actually return an object of type Answer without a place to hold on to the std::vectors you could allocate the relevant entities and accept that the result will yield a memory leak unless the caller can clean the result up.
You can't just cast stuff. struct Answer is expecting a char**, so you are going to have to build it and keep it valid as long as the struct Answer is in use. At least they were kind enough to let us know they don't intend to modify it or mess with cleaning up the memory, since it takes "const char * const *".
#include <iostream>
#include <vector>
#include <string>
#include <assert.h>
typedef std::vector<std::string> VectorOfStrings_type;
struct Answer
{
const char* const* lastNames;
unsigned numberOfPeople;
};
class AnswerWrapper
{
private:
// construct and maintain memory so the pointers in the Answer struct will be valid
char ** lastNames;
unsigned int numberOfPeople;
public:
AnswerWrapper(const VectorOfStrings_type &input){
numberOfPeople = input.size();
// create the array of pointers
lastNames = static_cast<char**>(
malloc(numberOfPeople * sizeof(char*))
);
// create each string
for (unsigned int i = 0; i < numberOfPeople; ++i){
const std::string &name = input[i];
// allocate space
lastNames[i] = static_cast<char*>(
malloc(name.size() + 1)
);
// copy string
strncpy(lastNames[i], name.data(), name.size());
// add null terminator
lastNames[i][name.size()] = '\0';
}
}
operator Answer (){
return Answer{ lastNames, numberOfPeople };
}
~AnswerWrapper(){
// critcally important, left as an exercise
assert(0);
}
};
void SomeFunctionWhichUsesAnswer(Answer a){
// presumably you have some legacy C code here
// but here's a quick and easy demo
for (unsigned int i = 0; i < a.numberOfPeople; ++i)
std::cout << a.lastNames[i] << std::endl;
}
int main() {
// Here is your vector of strings
VectorOfStrings_type myData { "custom formatted data goes here", "and more here", "and again" };
// You must construct a buffer for the "Answer" type, which must remain in scope
AnswerWrapper temp{ myData };
// AnswerWrapper is currently in scope, so inside this function, the pointers will be valid
SomeFunctionWhichUsesAnswer(temp);
}
Also, I noticed that the strings in Answer are not referred to as null terminated. That is a separate issue you can take care of.
A const member variable can only be assigned in the constructor.
if you can add to the struct, define a constructor, and use the : lastname(value) syntax; or use the struct Answer myVar{value,number}; initialization, right where you declare your instance.
Another - ugly, dangerous, and frowned upon - alternative is a cast: (char**) lastname = value;, or in C++ syntax reinterpret_cast<char**>(lastname) = value.
If someone is teaching you either of those approaches, change the teacher.

C++ Putting a string into a structure of vectors of strings

I have a problem in putting string value into a "structure of vectors of strings".
The simplest reproducible code is as follows:
#include <vector>
#include <string>
#include <iostream>
using namespace std;
struct ttt {
string name;
unsigned int ID;
vector<unsigned int> numList;
};
int main() {
vector<ttt> b;
b.reserve(3);
b[0].ID = 1;
b[0].numList.push_back(3);
b[0].numList.push_back(4);
string dd ("Desk");
b[0].name = dd;
cout << b[0].ID << b[0].name << b[0].numList[2] << endl;
return 0;
}
The code compiles, but it failed to put "Desk" string into b[0].name, a structure element. Segmentation Fault arose at the spot.
I also tried below lines but all of them failed.
b[0].name.push_back(dd);
b[0].name += dd;
My compiler is GCC g++ 4.7.7 20120313,
and I used below compile command.
/usr/bin/g++ --std=gnu++0x -Werror -Wall -Wextra -Warray-bounds
Any help would be deeply appreciated, sincerely.
There are two errors:
Assigning b[0] directly without calling push_back or without initializing it in a constructor call beforehand.
Another offending line is
b[0].numList[2]
because you only have called push_back() twice, and indexing is 0-based.
It would be much better to initialize the vector directly like this:
#include <string>
#include <vector>
#include <iostream>
using namespace std;
struct ttt {
string name;
unsigned int ID;
vector<unsigned int> numList;
};
int main() {
vector<ttt> b{{"Desk", 1, { 3, 4 }}};
cout << b[0].ID << b[0].name << b[0].numList[1] << endl;
}
Live Example
You may not use the subscript operator for an empty vector to assign new values to it. Use instead push_back member function.
For example
std::vector<ttt> b;
b.reserve( 3 );
//...
b.push_back( ttt() );
b.back().ID = 1;
//...
The first error reported by Valgrind on that code is
==28307== Conditional jump or move depends on uninitialised value(s)
==28307== at 0x40154F: void std::vector<unsigned int, std::allocator<unsigned int> >::emplace_back<unsigned int>(unsigned int&&) (vector.tcc:94)
==28307== by 0x4012D7: std::vector<unsigned int, std::allocator<unsigned int> >::push_back(unsigned int&&) (stl_vector.h:933)
==28307== by 0x400F00: main (39273136.cpp:17)
Whilst this might seem a bit cryptic, a bit of experience suggests to check whethe the this argument to push_back() is initialised. Looking through the code, we see:
vector<ttt> b;
b.reserve(3);
b[0].ID = 1;
b[0].numList.push_back(3);
You've told the vector to prepare to have 3 elements, but then you never add any ttt objects to it. When you access b[0], you're using uninitialised memory (Valgrind doesn't complain about the assignment to b[0].ID because the memory has been allocated and belongs to b - but calling push_back attempts to read vector members that may be random garbage).
The obvious solution is to emplace_back() (or otherwise create) the elements of b.
when you call reserve() on a vector, it doesn't create any instances of the contained type. It only allocates the space for the elements.. So when you try to access these locations in the vector, you get undefined behaviour. You must push elements into the vector first or zero-initialize them with a call like vector<ttt> b(6); before trying to do any read or write on them.
Editing just the one line where you declare the vector of ttts and removing the reserve() call fixes this program.
Also beware, because you try to access b[0].numList[2] , the third element, but you only did push_back for two elements.
#include <vector>
#include <string>
#include <iostream>
using namespace std;
struct ttt {
string name;
unsigned int ID;
vector<unsigned int> numList;
};
int main() {
vector<ttt> b(3); //create 3 zero-init elements in vector b
b[0].ID = 1;
b[0].numList.push_back(3);
b[0].numList.push_back(4);
string dd ("Desk");
b[0].name = dd;
cout << b[0].ID << b[0].name << b[0].numList[2] << endl;
//^beware, this hasn't been initialized
return 0;
}
Output: 1Desk0

New operator overloading causes Infinite recursion when inserting the address in a map

I am overloading the new operator to write my own custom memory monitoring class which has a map of address to bytes.
but unfortunately when I insert the address of the memory to a map, the map will create a new object and the overloaded new operator will get called again and creates a infinite recursion and memory leak.
I have added the code that causes the issue below.
Please advice.
#include <iostream>
#include <cstdlib>
#include <map>
using namespace std;
class MemoryManager{
static map<void* const, size_t> memory; //void* is an address, size_t is size
static void allocate(void* ptr, size_t size);
}
void MemoryManager::allocate(void* ptr, size_t size){
cout << ptr << endl; // prints the address
// inserts the address of the memory in a map.
// the compiler will create `new` object and creates a recursion.
// infinite recursion is created.
memory.insert(pair<void* const, size_t>(ptr, size));
totalBytes += size;
number_of_allocations++;
}
void* operator new (size_t size){
void* ptr = malloc(size);
MemoryManager::allocate(ptr, size);
return ptr;
}
int main(){
int* p1 = new int;
}
Don't do that.
If you must, get a copy of "the mallocator", the world's simplest allocator that uses malloc, or write one yourself. Use that allocator in your std::map to avoid it calling (non-placement) new.

How to cast void* back to std::vector<float>

I can construct data on Line 19 from vvp.at(0) if I know the size of vf.
#include <iostream>
#include <vector>
typedef void* VoidPointer;
typedef std::vector< float > VF;
typedef std::vector< VoidPointer > VVP;
int main(int argc, char** argv)
{
VF vf;
vf.push_back(13.0f);
vf.push_back(14.0f);
vf.push_back(15.0f);
vf.push_back(16.0f);
VVP vvp;
vvp.push_back( (VoidPointer)const_cast<float *>( &(vf.front()) ) );
VF data ( static_cast< float* >( vvp.at(0) ),
static_cast< float* >( vvp.at(0) ) + vf.size() );
std::cout << "data.size() is " << data.size() << std::endl;
for(VF::const_iterator i = data.begin(); i != data.end(); ++i)
{
std::cout << "data contains " << *i << std::endl;
}
return 0;
}
Leaving aside whether this is sensible (the example is contrived) I'd like to know how to cast vvp.at(0) to a std::vector<float> if I didn't know the size of vf. I'm thinking along the lines of something like:
std::vector<float> data( *static_cast< std::vector<float>* >( vvp.at(0) ) );
But that causes the program to termintate with std::bad_alloc, I don't mind copying if need be.
That is not a cast from vvp.at(0) to a vector, it's a copy of an array of floats into a new vector. And you can't copy it without knowing the length. You only saved a pointer to the first element, so the information was lost.
You could make std::vector<std::pair<VoidPointer, size_t> > VVP and save both &vf.front() and vf.size() (or start and end pointers, if you prefer).
You could make std::vector<VF *> and store pointers to vectors (i.e. vvp.push_back(&vf)) and now there's no casting at all.
Edit: In case you didn't realize: The pointer &vf is unrelated to &vf.front(). vf is a structure which contains the pointer &vf.front() (or a way to get it). There's no information in just the address &vf.front() to let you find &vf.
The only thing I can think of is extremely non-portable (and equally crazy). Each vector allocates a contiguous array of memory. Any allocation function has to keep track of how many bytes have been allocated, so that it can de-allocate them given only the beginning of the allocation's address.
AFAIK, the C++ standard does not specify how this book keeping is done and therefore, this up to each compiler. One method is to write a count before the actual allocation address - I believe this is what the Visual C++ compiler does. (Eg. if allocating at 0x104, a 32-bit count could be stored at 0x100). Again, you will have to know how your specific compiler does this book keeping.
Anyway, the point is, once you do, a little pointer arithmetic and de-referencing could theoretically look up the allocated size (I'm of course assuming you're still using a vector with a default allocator here), and figure out how many floats were actually allocated using only a void pointer.
Here's an example that works in Visual Studio in 32-bit debug mode:
#include <iostream>
#include <vector>
size_t bytes_allocated( void* p )
{
#ifndef _DEBUG
#error Doesn't work
#endif // _DEBUG
size_t const offset = 12;
size_t const counter_size = 4;
size_t const total_offset = offset + counter_size;
void* counter_address = ((char*)p)-total_offset;
size_t* count = reinterpret_cast<size_t*>(counter_address);
return *count;
}
int main(int argc, char* argv[])
{
typedef float test_type;
std::vector<test_type> v;
v.push_back(23);
v.push_back(23);
v.push_back(23);
size_t count = bytes_allocated(&v[0]);
std::cout<<count<<" bytes allocated\n";
std::cout<<count/sizeof(test_type)<<" items allocated\n";
return 0;
}
The output is:
12 bytes allocated
3 items allocated

Looking at the C++ new[] cookie. How portable is this code?

I came up with this as a quick solution to a debugging problem - I have the pointer variable and its type, I know it points to an array of objects allocated on the heap, but I don't know how many. So I wrote this function to look at the cookie that stores the number of bytes when memory is allocated on the heap.
template< typename T >
int num_allocated_items( T *p )
{
return *((int*)p-4)/sizeof(T);
}
//test
#include <iostream>
int main( int argc, char *argv[] )
{
using std::cout; using std::endl;
typedef long double testtype;
testtype *p = new testtype[ 45 ];
//prints 45
std::cout<<"num allocated = "<<num_allocated_items<testtype>(p)<<std::endl;
delete[] p;
return 0;
}
I'd like to know just how portable this code is.
It is not even remotely portable.
An implementation can perform heap bookkeeping however it wants and there is absolutely no way to portably get the size of a heap allocation unless you keep track of it yourself (which is what you should be doing).
You can globally overload new/delete operators on array, and put the size into the memory area. You get a portable solution.
The below code shows how:
void * operator new [] (size_t size)
{
void* p = malloc(size+sizeof(int));
*(int*)p = size;
return (void*)((int*)p+1);
}
void operator delete [] (void * p)
{
p = (void*)((int*)p-1);
free(p);
}
template<typename T>
int get_array_size(T* p)
{
return *((int*)p-1)/sizeof(T);
}
int main(int argc, char* argv[])
{
int* a = new int[200];
printf("size of a is %d.\n", get_array_size(a));
delete[] a;
return 0;
}
Result:
size of a is 200.
Not portable. But why not use std::vector? Then you can ask it directly how many elements it contains, and you won't need to worry about memory management and exception safety.