free std::string member of a struct allocated using malloc - c++

I am writing a c++ code. As a part of it, I use a C library quickjs.
This library allows creating dynamic memory using its custom js_mallocz call (which internally uses malloc), and freeing it later with js_free call.
I have a struct like this :
struct Person{
std::string id;
unsigned short age;
};
Which I have created using js_mallocz call, which is freed using the proper call.
//while assigning
auto person = (Person*) js_mallocz(ctx,sizeof(Person));
sole::uuid u4 =sole::uuid4();
std::string u = u4.base62();
person->id=u;
person->age=40;
//while freeing
js_free(ctx,person);
A code like this would give an error like :
24 bytes in 1 blocks are definitely lost in loss record 1 of 2
==30236== at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==30236== by 0x49D93FE: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.29)
==30236== by 0x11F93B: assign (basic_string.h:1370)
==30236== by 0x11F93B: operator= (basic_string.h:700)
I can't use new operator as I am required to use the memory allocation done by the third party lib quickjs. How do one free std::string in such struct created using malloc ?

Placement new is the way to solve this issue. (Concluded it based on from comments from #drescherjm)
So the code should be :
//while assigning
auto person = (Person*) js_mallocz(ctx,sizeof(Person));
person = new(person) Person(); //Placement new
sole::uuid u4 =sole::uuid4();
std::string u = u4.base62();
person->id=u;
person->age=40;
//while freeing
person->~Person(); //Manually call destructor
js_free(ctx,person);

Redefine your global operator new (all relevant varieties) in terms of js_mallocz and corresponding operator delete in terms of js_free.
Placement new is not a solution, because the C++ standard library and any third-party C++ library you happen to use will happily keep allocating memory for their internal needs with operator new. Not even speaking about needing to rewrite all of your code in this horrible style.

Related

Memory Leak caused by Initializer List?

I'm having memory leaks in my code, according to valgrind all of them come from the constructor in my class; here its code:
School::School(unsigned int NumberOfClasses[]) :
first(*new Grade<Student, std::equal_to<Student>>(NumberOfClasses[0])),
second(*new Grade<Student, std::equal_to<Student>>(NumberOfClasses[1])),
third(*new Grade<Student, std::equal_to<Student>>(NumberOfClasses[2])) {
}
Grade is a special array template I created that gets both an element (in this case, a Student) and a compare function for the element (which I also provided); it has both a Constructor and a Destructor that works without memory leaks. Here is the signature of the constructor:
Grade<Element, Compare> :: Grade(unsigned int size);
Since my school is 3 Grades, its destructor is =default;
This is what I get from valgrind:
8 bytes in 1 blocks are indirectly lost in loss record 1 of 6
==21426== at 0x4C2A888: operator new[](unsigned long) (vg_replace_malloc.c:423)
==21426== by 0x4041B8: Grade<BmbSchool::Student, std::equal_to<BmbSchool::Student> >::Grade(unsigned int) (GradeImp.h:9)
==21426== by 0x40298B: BmbSchool::School::Grade(unsigned int*) (School.cpp:27)
==21426== by 0x405B6C: main (BmbSchool.cpp:148)
Another kind of error I get, quite similiar, is:
==21426== 32 (24 direct, 8 indirect) bytes in 1 blocks are definitely lost in loss record 3 of 6
==21426== at 0x4C2A1E3: operator new(unsigned long) (vg_replace_malloc.c:334)
==21426== by 0x402974: BmbSchool::School::Grade(unsigned int*) (School.cpp:28)
==21426== by 0x405B6C: main (BmbSchool.cpp:148)
Any way it makes sense? How can I solve this? I can assume that there won't be any bad_alloc exceptions thrown when defining the arrays.
edit: The definition to school is -
Grade<Student, std::equal_to<Student>> first;
Grade<Student, std::equal_to<Student>> second;
Grade<Student, std::equal_to<Student>> third;
The leak is in your misuse of new. You are dynamically allocating 3 Grade objects, but are then dereferencing the pointers to pass those objects to the copy constructor of your 3 data members. You never delete the objects you new'ed, hence the leaking.
You don't need to use new at all in this situation. Simply pass your input values directly to the same constructor of the data members themselves that you were calling with new:
School::School(unsigned int NumberOfClasses[]) :
first(NumberOfClasses[0]),
second(NumberOfClasses[1]),
third(NumberOfClasses[2])
{
}
If you can use C++11 or later, you can use std::array, so something like
School::School(const std::array<unsigned int, 3>& NumberOfClasses) :
// as Remy Lebeau's answer
I would expect compilers to produce similar if not the same machine code, but you will gain some compile-time checking.

Newbie in vectors in C++

I am trying to understand how vectors work. From what I ve read they are a class that can be used as an array with many helpful functions to handle its elements. So I ve tried creating a vector of a class A which contains a vector of class B.
Here is the code:
#include <iostream>
#include <vector>
using namespace std;
class B
{
public:
B()
{}
void print()
{
cout<<"The mighty ";
}
~B()
{}
};
class A
{
B b;
vector<B> Blist;
public:
A()
{
cout<<"An A!"<<endl;
}
void pushb()
{
Blist.push_back(b);
}
void printb()
{
Blist[7].print();
}
void print()
{
cout<<"Kass Company"<<endl;
}
~A()
{
}
};
int main(void)
{
vector<A> Alist;
A a, b, c;
Alist.push_back(a);
Alist[1].printb();
Alist[1].print();
return 0;
}
Well, my problem is that... it works fine. If vectors work like arrays shouldnt the first object that gets pushbacked get the 0 position of the vector? As a result, shouldnt the program fail to run, since there is no object in the Alist[1] or the Blist[7]?
Thanks in advance!
Well, my problem is that... it works fine
Well, in fact it shouldn't, since you're accessing both Alist and Alist::Blist out of their bounds.
If vectors work like arrays shouldnt the first object that gets pushbacked get the 0 position of the vector?
The std::vector<T>::push_back function appends an element to the end of the vector, so the push-backed element is given the index size() - 1 (after the push, e.g. the old size()).
Check your bounds
When using std::vector, you are responsible for checking the bounds you're trying to access to. You can use std::vector<T>::size() for this check, or the function std::vector<T>::at(size_t) as said by Jarod42.
See the STL documentation for more information : http://www.cplusplus.com/reference/vector/.
Why it seems to work anyway
You're stumbling across undefined behavior but still, it seems to work fine. Why ?
Well, internally the vector holds a pointer to dynamically allocated memory, holding the vector contents. The class encapsulates all the nasty memory management (calling new, delete, resizing the array, etc.).
When you're calling std::vector<T>::operator[](size_t), by doing for example Alist[1], it simply boils down to dereferencing the internal array at the given index (without bound checking).
Using a bad index, you end up reading some memory past the end of the allocated region, that does not contain any meaningful data, and is probably either uninitialized or zero'ed out. In conclusion when you're doing Alist[1], you're getting some garbage memory interpreted as an A instance.
Now why the hell doing Alist[1].print() does not crash ? Because the function A::print() is not using of the class members, and doing a->print() simply does not uses a contents.
You can verify this using this program (please don't actually use this, it is just intended for this demonstration) :
int foo = 0xDEADBEEF;
A& z = static_cast<A&>(*((A*) &foo));
z.print();
This code simply uses the memory occupied by the integer value foo as an A instance (much like you're using uninitialized memory when accessing the vector out of bounds), and calls the A::print() function.
You can try this for yourself, it works as expected ! This is because this member function does not need to use the actual memory content of the instance, and will run no matter z points to garbage or not.
How to debug and check this program
Use valgrind (http://valgrind.org/). Definitely.
Using valgrind's memcheck, you can track down invalid reads and writes (as well as other memory related stuff) :
you$ valgrind --tool=memcheck a.out
==1785== Memcheck, a memory error detector
==1785== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==1785== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==1785== Command: ./a.out
==1785==
An A!
An A!
An A!
==1785== Invalid read of size 8
==1785== at 0x400F14: std::vector<B, std::allocator<B> >::operator[](unsigned long) (stl_vector.h:771)
==1785== by 0x400E02: A::printb() (main.c:34)
==1785== by 0x400C0D: main (main.c:51)
==1785== Address 0x5a12068 is 8 bytes after a block of size 32 alloc'd
==1785== at 0x4C28965: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==1785== by 0x4022E5: __gnu_cxx::new_allocator<A>::allocate(unsigned long, void const*) (new_allocator.h:104)
==1785== by 0x401D20: std::_Vector_base<A, std::allocator<A> >::_M_allocate(unsigned long) (in /home/amonti/.local/share/people/temp/a.out)
==1785== by 0x4013F8: std::vector<A, std::allocator<A> >::_M_insert_aux(__gnu_cxx::__normal_iterator<A*, std::vector<A, std::allocator<A> > >, A const&) (vector.tcc:345)
==1785== by 0x401017: std::vector<A, std::allocator<A> >::push_back(A const&) (stl_vector.h:913)
==1785== by 0x400BF4: main (main.c:50)
==1785==
The mighty Kass Company
==1785==
==1785== HEAP SUMMARY:
==1785== in use at exit: 0 bytes in 0 blocks
==1785== total heap usage: 1 allocs, 1 frees, 32 bytes allocated
==1785==
==1785== All heap blocks were freed -- no leaks are possible
==1785==
==1785== For counts of detected and suppressed errors, rerun with: -v
==1785== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 3 from 3)
In this trace valgrind detects an invalid read (of size 8 because you're reading a pointer on a 64-bit platform) at main.c:34 :
Blist[7].print();
So you can verify that you're doing something wrong.
in your case the output maybe a trash result because the logic of the vector data structure is that its a dynamic array that expands it self(by a constant range ) when it reaches the last free space .
for example when first creating a vector it has 10 spaces when it reaches the 10 space it becomes 20 and in this stage the vec[11] has a trash value.
This is exactly why you're supposed to use vector::at() instead of vector::operator[] when you're testing/writing your program for the first time.
You can use macros and preprocessor defines to declare that you're compiling for debug, such as:
#ifdef THISISDEBUG
return myvec.at(5);
#else
return myvec[5];
#endif
Then you tell your makefile to define THISISDEBUG when you're debugging/testing.
The difference between at() and operator[], is that at() throws an exception if you're out of range, while operator[] accesses memory directly.
In C++, you're generally allowed to read any place in memory (at least in Windows and Linux), but you're only allowed to write into places that belong to your program. Your operating system protects you! Imagine you do what you did up there, and you try to modify something that doesn't belong to your proram. Back then in the 80s and 90s, this would've been accepted and would've lead to a blue screen. Now, your operating system raises a SEGFAULT.
On the other hand, the reason why you're seeing a result there, is because deleting an object doesn't necessarily mean resetting values in memory. It just means that your program tells the operating system: "look, I don't need this region of memory anymore". So, your operating system can assign this region to another program. So, if you try to read that region again, it will work, but you'll get garbage! That's exactly what this technically is called. Like when you do:
double x;
std::cout << x << std::endl;
What is the value that will be printed? It's garbage. It's the remnant of some other program that freed that memory.
Basicly vectors are arrays class.
vector <string> arr; // defines that this is array
vector <MyClass *> arrw; // defines that this is array to my created class vector
Vector is useful to use, when you don't know how much array elements you need. For example, read lines from file. To add new element to vector you can use arr.insert(arr.end(), ""); and add.insert(arr.end(), new MyClass); (I like this better then push_back, becouse You can insert in any place of vector.)
You can access you array element by the same way:
arr[2];
Also it's useful to know some tricks like get access to last element; arr[arr.size() - 1] i. (arr.size() will return INT [elements in array]. And -1 will count it for good index. Othewise you will get segmentation error).
P.S. There is no difference between vector Class and array, ecxept this methods, that allow add new elements, when you don't know how big your array will be.

How to assign value of a string variable to a string variable of a structure in c++?

I am trying to assign the value of a string variable to another string variable of a structure. But gdb gives an runtime error. The error is as follows:
Program received signal SIGSEGV, Segmentation fault.
0xb7f7c8f8 in std::string::assign(std::string const&) ()
from /usr/lib/i386-linux-gnu/libstdc++.so.6
My C++ program is:
#include<iostream>
#include<stdlib.h>
#include<string>
typedef long unsigned int LUI;
using namespace std;
struct graph {
string string_node;
LUI node;
struct graph *link;
};
struct graph *abc[30];
struct graph *t;
string x;
int main() {
t = (struct graph *) malloc(sizeof(struct graph *));
x = "abc";
t->string_node = x;
t->link = NULL;
abc[0] = t;
cout << "Value is " << abc[0]->string_node << endl;
cout << "end";
return 0;
}
Please help me to store the value of x into t->string_node. Thanks in advance..
t = (struct graph *) malloc(sizeof(struct graph *));
graph is a class. It contains C++ classes, specifically it contains a std::string.
All C++ classes must be constructed in dynamic scope using the new operator. They cannot be constructed with the C library function malloc(), which knows absolutely nothing, whatsoever, about C++ classes. Doing so results in undefined behavior (not to mention that your malloc-ed size is wrong, anyway).
Now that you're writing C++ code, you need to completely forget that malloc(), realloc(), and free() ever existed, and always use new and delete.
Your problem is that you're allocating a struct with malloc, but that struct does not have only POD (plain old data) members: it has a std::string member, and std::string objects expect to be constructed. Simply allocating memory for it with malloc will not invoke the std::string constructor, and consequently attempting to interact with that std::string later will result in undefined behavior since that object is in a bad state.
You instead should use new to allocate your struct, and that will properly allocate memory and invoke the default constructor for each member. (Conversely, you should release that memory with delete instead of free to properly invoke the destructor of each member.)
Alternatively, it is possible to use "placement new" to construct an object in memory you've already allocated, but this is not something that you should normally need to do.

Segmentation fault assigning std::string in a struct [duplicate]

This question already has answers here:
How to use a C++ string in a structure when malloc()-ing the same structure?
(5 answers)
Closed 9 years ago.
the following code results in a segmentation fault when it's run and I can't figure out why:
#include <cstdlib>
#include <string>
#include <iostream>
using namespace std;
struct Token
{
int num;
string val;
};
int main()
{
Token* tok = (Token*) malloc (sizeof(Token));
tok -> val = "myval";
std::cout<<tok->val;
}
see backtrace:
0 0x00007ffff7b95d9b in std::string::assign(char const*, unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6;
1 0x0000000000400867 in main ()
Don't use malloc in C++ code, it's rarely the correct choice.
Your options are:
Token tok;
tok.val = "myval";
auto tok = std::make_unique<Token>(); // C++14
tok->val = "myval";
auto tok = std::unique_ptr<Token>(new Token()); // C++11
tok->val = "myval";
auto tok = std::make_shared<Token>(); // C++11, use if resource is shared
tok->val = "myval";
Token* tok = new Token();
tok->val = "myval";
delete tok;
These options should suffice for most cases.
Prefer the options from top to bottom: The default way should be creating objects, then unique_ptr, then shared_ptr and only if absolutely necessary you should deal with raw pointers.
The reason for that is easy: Exception safety and memory leaks. An object cannot be leaked, you can't forget to delete a unique_ptr or a shared_ptr, but you can with a raw pointer. Additionally, the raw pointer won't ever get deleted in case of an exception. unique_ptr should be preffered to shared_ptr because shared_ptr has overhead (an atomic counter to make it thread safe).
Demo that everything compiles fine (without C++14 make_unique): Demo
malloc does not call any constructors. Try using new and it should work fine.
Also don't forget to delete it afterwards, or either use smart pointers or directly put the variable on the stack.
Here's why you cannot use malloc with std::string:
You can't malloc a class with non-trivial constructor in C++. What you
get from malloc is a block of raw memory, which does not contain a
properly constructed object. Any attempts to use that memory as a
"real" object will fail.
As well as (already pointed out in other answers):
The problem is that malloc does not call the constructor of example.
Since a string is usually represented as a pointer on the stack, this
is set to zero, and you dereference a null pointer. You need to use
new instead.
If you insist on using malloc, you can either use placement new (see the link for details) or just use a plain ol' const char*:
struct Token
{
int num;
const char* val;
};
int main()
{
Token* tok = (Token*) malloc (sizeof(Token));
tok->val = "myval";
std::cout << tok->val;
free(tok);
} // will not seg fault

Memory allocation question in C++

int main() {
char** k;
k = new char*;
char* k1 = "abc";
char* k2 = "def";
*k = k1;
*(k + 1) = k2;
delete [] (k + 1);
}
Error: segmentation fault
Could someone explain why I get segmentation fault when freeing (k + 1)? I was able to free k with no problems.
ADD: In the answers it has been said that I can't delete [] (k + 1) since I haven't used new on it; But how do you explain the fact that cout<<*(k + 1)<<endl; printed correctly?
k = new char*;
This allocated storage for only a single char*.
*(k + 1) = k2;
This tries to pretend there are two char*s allocated. This may not be the site of the segfault, but it is the error.
delete [] (k + 1);
Here you're trying to delete[] something you did not new[], another error.
EDIT: Deep down, memory is allocated in large chunks, such as pages. So when you allocate a small bit of storage, it's very likely that the memory around it is also valid. It's still very invalid to access it, though.
More to the point, when you say something like new char*, this turns into a call to operator new(sizeof(char*)). Let's say the OS allocates a new 4K page of physical RAM for that at address 0x12340000. The memory manager needs a small structure in there to keep track of the block, something like:
struct mem_block_info {
void* next_block;
size_t block_size;
};
So it puts this structure at 0x12340000. Immediately after that, it puts the storage you requested, so (assuming this is a 32-bit machine) it returns a pointer of 0x12340008, since sizeof(void*) == sizeof(size_t) == 4. Then it needs to put a header after your storage to track the unused part of that 4K page, so it doesn't waste memory by allocating another 4K page when you want another char*. That header goes at the address right past the end of your allocated block, 0x1234000C. Once the dust settles, that new char* has put this in memory:
Address Data
0x12340000 0x00000000
0x12340004 0x00000001
0x12340008 uninitialized; could be anything
0x1234000C 0x00000000
0x12340010 0x00000FF4
The null pointers indicate the end of the allocated and free block linked lists.
So when you do:
*(k + 1) = k2;
k + 1 == 0x1234000C is the next_block pointer for the free block, and you just overwrote it with an invalid value (the address of a string in read-only memory, most likely). This does not immediately cause a segmentation fault, but when the memory manager tries to traverse the free block list, it will wind up looking at that string and misinterpreting it as a block header, then going to the next_block from there which is an invalid address, and boom, segfault.
One can only delete exactly what is returned from new, and same applies to new[] and delete[].
It is Undefined Behavior to pass any address to delete which was not returned by new.
Here is the quote from the C++ Standard.
ยง 3.7.4.2-3
If a deallocation function terminates by throwing an exception, the behavior is undefined. The value of the first argument supplied to a deallocation function may be a null pointer value; if so, and if the deallocation function is one supplied in the standard library, the call has no effect. Otherwise, the value supplied to operator delete(void*) in the standard library shall be one of the values returned by a previous invocation of either operator new(std::size_t) or operator new(std::size_t, const std::nothrow_-t&) in the standard library, and the value supplied to operator delete[](void*) in the standard library shall be one of the values returned by a previous invocation of either operator new[](std::size_t) or operator new[](std::size_t, const std::nothrow_t&) in the standard library.
k + 1 isn't created using new[]. How can you then delete[] it?
They always come in pairs.
You can delete only the exact pointers returned by new. Everything else is illegal.