copy elision using STL (vector as example) - c++

I was reading about the copy elision in c++. And i was having doubts about STL in c++ using this copy elision.
The following code:
#include <vector>
#include <iostream>
using namespace std;
vector<int> merge(vector<int> &arrA, vector<int> &arrB)
{
int x;
vector<int> result;
for(x = 0; x < arrA.size(); x++)
{
result.push_back(arrA[x]);
}
for(x = 0; x < arrB.size(); x++)
{
result.push_back(arrB[x]);
}
cout << "fun return: " << &result <<endl;
return result;
}
int main(int argc, char const *argv[])
{
vector<int> arrA;
arrA.push_back(1);
vector<int> arrB;
arrB.push_back(2);
vector<int> res;
res = merge(arrA, arrB);
cout << "return: " << &res <<endl;
return 0;
}
So I was doing a simple task (merging) the vectors A and B (do not pay attention to the process, just the function and return.
vector<int> merge(vector<int> &arrA, vector<int> &arrB)
With the following definition it is returning a vector<int> (no reference)
And also return result; which is the variable declared in the function scope.
I was trying to see the memory address at which these vectores are located.
output:
==5036== Memcheck, a memory error detector
==5036== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==5036== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==5036== Command: ./a.out
==5036==
fun return: 0xffefffe40
return: 0xffefffe20
==5036==
==5036== HEAP SUMMARY:
==5036== in use at exit: 0 bytes in 0 blocks
==5036== total heap usage: 5 allocs, 5 frees, 28 bytes allocated
==5036==
==5036== All heap blocks were freed -- no leaks are possible
==5036==
==5036== For counts of detected and suppressed errors, rerun with: -v
==5036== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
The memory address is different for both so I was thinking that as long as it will no make a copy-construtor, it will be the same memory address at the end (0xffefffe40) Does that means it is copy-constructed?
Is this method being copy elision?
if not: why it is not copy elision?
if yes: How can I know it is really doing the copy elision?
And the important one: if this is not being copy elision, is it possible to do it? what is needed in order to do the copy elision in STL?

For copy elision, you need to have the "copy" in the first place, i.e. your res vector has to be copy constructed from the return value.
Otherwise you'll just have an assignment, which requires getting rid of whatever was in the vector and as such cannot be elided.
Notice that it would still be a move assignment, so the drawback won't be that much (You can test it with memcheck too).

Related

Why does memory leak in one case and not in another

I am creating a c++ object with two slightly different ways, in the following code when CASE is 0 there is a memory leak, but no memory leak in the else case.
#include <string>
#define CASE 1
class A {
private:
std::string *s;
public:
A(std::string *p_s) { s = p_s; }
};
int main() {
#if CASE==0
auto a = A(new std::string("Hello"));
#else
auto s = std::string("Hello");
auto a = A(&s);
#endif
}
when I set CASE 0 the valgrind says that there is a memory leak
valgrind ./a.out
==24351== Memcheck, a memory error detector
==24351== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==24351== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==24351== Command: ./a.out
==24351==
==24351==
==24351== HEAP SUMMARY:
==24351== in use at exit: 32 bytes in 1 blocks
==24351== total heap usage: 2 allocs, 1 frees, 72,736 bytes allocated
==24351==
==24351== LEAK SUMMARY:
==24351== definitely lost: 32 bytes in 1 blocks
==24351== indirectly lost: 0 bytes in 0 blocks
==24351== possibly lost: 0 bytes in 0 blocks
==24351== still reachable: 0 bytes in 0 blocks
==24351== suppressed: 0 bytes in 0 blocks
==24351== Rerun with --leak-check=full to see details of leaked memory
==24351==
==24351== For counts of detected and suppressed errors, rerun with: -v
==24351== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
in the else case (i.e. define CASE 1) it works as expected and valgrind doesn't report any memory leak.
I am not able to understand in either case I am passing a pointer and I am not explicitly freeing the memory then why do they behave differently?
The reason for this behavior is that your class A is not designed to take ownership of std::string* passed into it: its std::string *s member assumes that the object the pointer to which is passed into the constructor would be destroyed externally.
This leads to a memory leak when the object is not destroyed: delete is never called on new string passed into the constructor in the first case, causing a memory leak.
In the second case the pointer points to a string in automatic storage. It gets destroyed when main ends, preventing the memory leak.
You don't get a memory leak because you have a pointer.
You get a memory leak because you new'd something and did not delete it.
Obtaining a pointer to an automatic storage variable does not stop the variable from being cleaned up automatically.
In fact, attempting to delete &a in that case would be wrong/broken/evil/illegal/heresy.
CASE==0
auto a = A(new std::string("Hello"));
This means you are new-ing an object in heap -> you have to explicitly delete it - that you didn't in the snippet -> memory leaks.
else
auto s = std::string("Hello");
auto a = A(&s);
auto s = std::string("Hello");: This means you are creating an object in stack and,
auto a = A(&s);: take its address (in stack, of course).
The created object will be auto-deleted once the variable goes out of scope
-> no memory leak.
This is no different from:
// first case, leak
int *j = new int (5);
//
// second case, no leak
int q = 5;
int *j = &q;
In the first case, we've allocated memory with new and it's our responsibility to delete it when we're done. In the second case, we create q on the stack and it's destroyed when it goes out of scope.

Memory leaks when allocating struct containing stl vector

I want to allocate memory for a struct that contains std::vector. After allocating it, I will push_back some data to it.
After all, I need to destroy my allocated struct. I want to know how can it be done with no memory corruption.
Here is my code:
typedef struct my_struct_t{
int a, b;
vector<unsigned> vec;
}
} MYSTRUCT;
int main(int argc, const char * argv[])
{
MYSTRUCT* ptr_s = new MYSTRUCT;
for(int i = 0 ; i < 100 ; i++){
ptr_s->vec.push_back(i);
}
ptr_s->vec.clear();
delete ptr_s;
return 0;
}
I tried to use clear as it is supposed to call destructor. But after valgrind-ing my code, there are still some blocks reachable. I also tried to deallocate vector using this:
vector<unsigned>().swap(ptr_s.vec)
But with no success.
output of `valgrind':
==52635== HEAP SUMMARY:
==52635== in use at exit: 10,360 bytes in 5 blocks
==52635== total heap usage: 147 allocs, 142 frees, 25,198 bytes allocated
==52635==
==52635== LEAK SUMMARY:
==52635== definitely lost: 0 bytes in 0 blocks
==52635== indirectly lost: 0 bytes in 0 blocks
==52635== possibly lost: 0 bytes in 0 blocks
==52635== still reachable: 10,360 bytes in 5 blocks
==52635== suppressed: 0 bytes in 0 blocks
==52635== Reachable blocks (those to which a pointer was found) are not shown.
==52635== To see them, rerun with: --leak-check=full --show-leak-kinds=all
Thank you everyone in advance.
update:
I noticed that the source of memory corruption in my application is in somewhere else. So I added an update. Here is the new code:
MYSTRUCT* ptr_s1 = new MYSTRUCT;
MYSTRUCT* ptr_s2 = new MYSTRUCT;
for(int i = 0 ; i < 100 ; i++){
ptr_s1->vec.push_back(i);
}
memcpy(ptr_s2 , ptr_s1, sizeof(*ptr_s1));
delete ptr_s1;
delete ptr_s2; // here I get seg fault
return 0;
As soon as deleting ptr_s2, seg fault happens.
Update: proper way, based on the accepted answer:
typedef struct my_struct_t{
int a, b;
vector<unsigned> vec;
inline my_struct_t operator=(const my_struct_t &s ){
a = s.a;
b = s.b;
vec = s.vec;
return s;
}
} MYSTRUCT;
MYSTRUCT* ptr_s1 = new MYSTRUCT;
MYSTRUCT* ptr_s2 = new MYSTRUCT;
for(int i = 0 ; i < 100 ; i++){
ptr_s1->vec.push_back(i);
}
// no memcpy
// memcpy(ptr_s2 , ptr_s1, sizeof(*ptr_s1));
*ptr_s2 = *ptr_s1;
delete ptr_s1;
delete ptr_s2; // no more sget seg fault
return 0;
You don't need to call std::vector::clear or do something else, the destructor will get called when you delete it via delete ptr_s;.
The still reachable matter is explained in Valgrind FAQ.
My program uses the C++ STL and string classes. Valgrind reports
'still reachable' memory leaks involving these classes at the exit of
the program, but there should be none.
First of all: relax, it's probably not a bug, but a feature. Many
implementations of the C++ standard libraries use their own memory
pool allocators. Memory for quite a number of destructed objects is
not immediately freed and given back to the OS, but kept in the
pool(s) for later re-use. The fact that the pools are not freed at the
exit of the program cause Valgrind to report this memory as still
reachable. The behaviour not to free pools at the exit could be called
a bug of the library though.
Update:
Briefly, don't copy classes with memcpy, if you use memcpy to copy a class object whose destructor deletes a pointer within itself (std::vector member in your case), you will end up with double delete when the second instance of the object is destroyed.
The right way is copy/move constructor and/or assignment operator for classes.

C++ destructor and memory allocation, and undefined beahviour

Firstly: I know that if the destructor of an object throws the behavior of the application cannot be counted on... The question is about memory issues.
So, now that this is clear:
See the app:
#include <stdlib.h>
#include <iostream>
class T
{
public:
T() : ma(0)
{std::cout << "T::T ->default<-" << std::endl; }
T(const char* a) : ma(a)
{std::cout << "T::T ->" << ma << "<-" << std::endl; }
~T()
{std::cout << "T::~T ->" << ma << "<-" << std::endl; }
private:
const char* ma;
};
int main()
{
T* t = new T();
delete t;
}
and see it's valgrind output:
$ valgrind ./a.out
==29554== Memcheck, a memory error detector
==29554== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==29554== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==29554== Command: ./a.out
==29554==
T::T ->default<-
T::~T ->==29554==
==29554== HEAP SUMMARY:
==29554== in use at exit: 0 bytes in 0 blocks
==29554== total heap usage: 1 allocs, 1 frees, 4 bytes allocated
==29554==
==29554== All heap blocks were freed -- no leaks are possible
==29554==
==29554== For counts of detected and suppressed errors, rerun with: -v
==29554== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Explanation: T::~T ->==29554== tells me the destructor has encountered a dangerous sitation (std::cout took in a null value which is undefined) so the behaviour of the application is uncontrollable...
Since it does not print out the "<-" and it gives me the valgrind prompt immediately I expect it exited at that specific point. Valgrind does not report any segfault or something like that ...
But also, valgrind reports no memory leaks... and this is confusing me ... so what I think that happens is:
I call delete t;
the application frees the memory of t
the destructor of t is called.
Can you please explain what is happening here?
Edit: To have a more clear question:
Is the destructor called on the freed memory or there is no undefined behaviour in the destructor when std::cout gets a null object?
Undefined behaviour is undefined.
If I had to guess, it looks like, in this case, the stream detects the null pointer and goes into an error state, so you simply don't see any more output. The rest of the delete process apparently continues as expected.
Other forms of undefined behaviour, for example actually dereferencing a null pointer, might give different results. Likewise, other stream implementations may behave differently when you break their requirements.
Valgrind is right, there is no memory leak.
You allocated in the heap the Variable t but not the inner workings of the Class T. So the destructor has nothing to deallocate since you took the responsibility of deallocating the memory using delete.
You could allocate a variable inside Class T and not deallocating it in the destructor to see a memory leak.

Valgrind legitimate "possibly lost" bytes example

I saw that valgrind classifies memory leaks into:
definitely lost
indirectly lost
possibly lost
still reachable
suppressed
I just fixed a leak where the "possibly lost" was the main problem.
The documentation says: "possibly lost means your program is leaking memory, unless you're doing unusual things with pointers that could cause them to point into the middle of an allocated block; see the user manual for some possible causes"
May I please know an example of "doing unusual things with pointers that could cause them to point into the middle of an allocated block" ?
I mean an example where "possibly lost" can be ignored although it is reported by valgrind. An example in which the use of pointers makes valgrind complain but at the same time the use of the pointers in that way is somehow legitimate
Thank you
Some examples of what the documentation are different libraries that have their own allocators and for which the memory returned is not directly the pointer returned by the underlying OS allocator (malloc/sbrk), but a pointer after an offset. Consider for example, an allocator that obtained some extra memory and stored meta information (maybe type information for a garbage collector...). The process of allocation and deallocation would be similar to:
void* allocate( size_t size ) {
metainfo_t *m = (metainfo_t*) malloc( size + sizeof(metainfo) );
m->data = some_value;
return (void*)(m+1); // [1]
}
void deallocate( void* p ) {
metainfo_t *m = ((metainfo_t*)p) - 1;
// use data
}
void * memory = allocate(10);
When valgrind is tracking the memory, it remembers the original pointer that was returned by malloc, and that pointer is not stored anywhere in the program. But that does not mean that the memory has been leaked, it only means that the pointer is not directly available in the program. In particular memory still holds the returned pointer, and deallocate can be called to release it, but valgrind does not see the original returned pointer at location (char*)memory - sizeof(metadata_t) anywhere in the program and warns.
char *p = malloc(100);
if (p != 0)
{
p += 50;
/* at this point, no pointer points to the start of the allocated memory */
/* however, it is still accessible */
for (int i = -50; i != 50; i++)
p[i] = 1;
free (p - 50);
}
char *p = malloc(100);
if (p != 0)
{
p += 50;
/* at this point, no pointer points to the start of the allocated memory */
/* however, it is still accessible */
for (int i = -50; i != 50; i++)
p[i] = 1;
free (p - 50);
}
Since it looks very interesting, I did run the code and valgrind it. The result is the following.
yjaeyong#carbon:~$ valgrind test
==14735== Memcheck, a memory error detector
==14735== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==14735== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright info
==14735== Command: test
==14735==
==14735==
==14735== HEAP SUMMARY:
==14735== in use at exit: 0 bytes in 0 blocks
==14735== total heap usage: 32 allocs, 32 frees, 2,017 bytes allocated
==14735==
==14735== All heap blocks were freed -- no leaks are possible
==14735==
==14735== For counts of detected and suppressed errors, rerun with: -v
==14735== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 6)
It says no leaks are possible. Am I missing anything?

vector pointer causing valgrind memory leak

I'm trying to learn C++ and valgrind. So I wrote the following code to test it out. But I get some memory leaks. Can anyone explain what's causing the memory leak? Thanks in advance.
#include <vector>
#include <iostream>
using namespace std;
class test
{
int c;
public:
void whatever();
};
void test:: whatever()
{
vector<test*> a;
if(true)
{
test* b = new test();
b->c = 1;
a.push_back(b);
}
test* d = a.back();
cout << "prints: " << d->c;
delete d;
}
int main()
{
test* a = new test();
a->whatever();
return 1;
}
from valgrind
==28548== HEAP SUMMARY:
==28548== in use at exit: 4 bytes in 1 blocks
==28548== total heap usage: 3 allocs, 2 frees, 16 bytes allocated
==28548==
==28548== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==28548== at 0x4C27CC1: operator new(unsigned long) (vg_replace_malloc.c:261)
==28548== by 0x400C36: main (in a.out)
==28548==
==28548== LEAK SUMMARY:
==28548== definitely lost: 4 bytes in 1 blocks
==28548== indirectly lost: 0 bytes in 0 blocks
==28548== possibly lost: 0 bytes in 0 blocks
==28548== still reachable: 0 bytes in 0 blocks
==28548== suppressed: 0 bytes in 0 blocks
==28548==
==28548== For counts of detected and suppressed errors, rerun with: -v
==28548== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
Am I not allowed to delete from a copy of a pointer or am I doing something else wrong?
You never call delete on a.
Of course, the important bit here is that you are using a vector of pointers. Why in the world would you do this? Let the vector take care of memory management for you!
You forgot to delete a; at the end of main().
Note that everything you wrote should never go into real code. You should never use dynamic allocation (new) unless you absolutely have to and know precisely why.
Assuming you want to maintain the vector of pointers for educational purposes, then here's a better way of writing it:
#include <vector>
#include <memory> // for unique_ptr
// intentionally left blank; NO abusing namespace std!
struct Foo
{
int c;
void whatever()
{
std::vector<std::unique_ptr<test>> v;
if (true)
{
v.emplace_back(new test);
v.back()->c = 1;
}
// everything is cleaned up automagically
}
};
int main()
{
Test a; // automatic, not dynamic
a.whatever();
return 1;
}
This is still just for educational purposes; in real life you would try very hard to make do with a plain std::vector<test>, since vector is already a dynamic data structure and there is little need for the extra level of indirection.
The memory leak is in main. You are not deleting the allocated test object.