What is wrong in the following snippet? - c++

I know it is a fairly basic violation, but what is it?
class xyz
{
void function1()
{
cout<<"in class";
}
};
int main()
{
xyz s1 = new xyz(100);
xyz s2 = s1;
s2.function1();
delete s1;
return 0;
}
Something is wrong about the memory allocation using new. I believe but I can't seem to understand the fundamental behind it and the resolution.

You can't assign T* to T (pathological cases aside).
xyz * s1 = new xyz();
xyz * s2 = s1;
s2->function1();
delete s1;
return 0;
Better yet, don't use naked new and delete and use a smart pointer:
auto s1 = make_unique<xyz>();
xyz * s2 = s1.get(); // non-owning pointer
s2->function1();
// no explicit delete necessary

new returns a pointer (xyz *) to an object, not an object, so you should correct the type of s1:
xyz* s1=new xyz(100);
and to call the method through the pointer you should use operator ->:
s1->function1();
which is the equivalent of dereferencing the pointer and calling the method on the object:
(*s1).function1();

Related

The WTF behavior in class's dynamically allocated char array

I crashed application every time I ran the code below. During debugging, I saw that the str object was self-destructing itself after the second line in main(). And it's quite a mystery for me. Try run it yourself:
#include<iostream>
class String {
private:
char* string = nullptr;
int length = 0;
public:
String(const char str[]) {
for (length; str[length] != '\0'; ++length);
string = new char[length + 1]{};
for (int i{}; i < length; ++i)
string[i] = str[i];
string[length] = '\0';
}
~String() {
delete[] string;
}
auto print() {
for (int i{}; i < length; ++i)
std::cout << string[i];
std::cout << '\n';
return *this;
}
auto getStrPtr() {
return string;
}
};
int main() {
String str("123");
auto strPtr{ str.print().getStrPtr() };
strPtr[0] = '3';
}
Am I missing something?
Note on line 2 in main(): I am trying to print the str's string array and then, since print() returns *this, I can chain methods and am calling a function that returns string's pointer. But, even if in debugger it all executes perfectly, I have no idea why the hell str object deconstructs itself after.
str object is not destroyed on the second line of main. The temporary copy of str is destroyed.
Temporaries are destroyed at the end of full expression. This is normal.
Your class deletes a pointer member in destructor, but fails to maintain class invariant of uniqueness of that pointer. The behaviour of the program is undefined when the destructor of str deletes the same pointer value as the destructor of the temporary object deletes. Behaviour is undefined even before that when strPtr[0] = '3'; indirects through the pointer that was deleted in the destructor.
Solution: Don't use owning bare pointers. Use smart pointer or container instead. std::string seems appropriate here.
But why that temporary object was created in the first place?
Because you return a String object in print. You initialise it with *this, and therefore that object is a copy. You don't use the returned object to initialise a variable, so a temporary object is materialised.

C# style string implementation in c++

I'm trying out a C# style string implementation in C++.
I have created an object and a pointer for class String, and assigned the object to the pointer. When i try to modify the object via the pointer instead of modifying the existing object i want to create a new object and make the pointer point it.
So i have overloaded the "=" operator, and creating a new object in the operator overloaded method. In order to reflect the change i need to use ss=*ss = "name";
Any suggestion to improve this code.
Below is my sample code
class String
{
char *str;
public:
String(char* str_in)
{
str = new char[strlen(str_in)];
strcpy(str, str_in);
}
String* operator=(char* s)
{
return new String(s);
}
};
int main()
{
String s="sample";
String *ss;
ss = &s;
ss=*ss = "name";
return 0;
}
I also tried to modify the this pointer, but not working as expected
String *ptr;
ptr = const_cast<String*>(this);
ptr = new String(s);
I would recommend some changes like this:
#include <string.h>
class String
{
char *str;
public:
String(const char* str_in)
{
str = new char[strlen(str_in)];
strcpy(str, str_in);
}
~String()
{
delete [] str;
}
String& operator=(const char* s)
{
char* tmp = new char[strlen(s)];
strcpy(tmp, s);
delete [] str;
str = tmp;
return *this;
}
};
int main()
{
String s("sample");
String *ss;
ss = &s;
ss = new String("name");
delete ss;
return 0;
}
First of all, you need an appropriate destructor or you are going to have a memory leak when String gets destroyed. Deleting the char* fixes this (since it is an array, we use the array delete).
Secondly, in C++, we almost always return a reference for operator= (not a pointer). So this revised operator= function is probably better - it deletes the old string, allocates memory for the new string, copies the new string, and returns *this.
Third, you can use const char* instead of char* for the constructor and assignment operator since you are not editing it.
In main(), I also created a new object for the pointer to point to since you requested that in the original post (and then it is deleted afterwards to avoid a memory leak).
Let me know if you have any questions with those changes.

Is a pointer to a stack object deleted when out of scope?

I'm having a hard time trying to understand exactly what I'm supposed to do with my pointer members in my classes. I know that any pointer created with new[] must be deleted with delete[]
But, what if my pointer points to the address of an object created on the stack? Do I have to delete it? Or will it be deleted when the class is destroyed. And if so, in what way am I supposed to delete it? The clarify the issue, here's some of my code.
Moves header file: Moves.h
#pragma once
#include "ShuffleBag.h"
class Character;
class Moves
{
private:
Character* pm_User;
ShuffleBag m_HitChances;
public:
Moves (Character& user);
~Moves ();
};
We can see that I have a pointer member to a character object.
Moves Source File: Moves.cpp
#include "Moves.h"
#include "Character.h"
Moves::Moves (Character& user)
{
m_HitChances = ShuffleBag ();
m_HitChances.Add (true, 8);
m_HitChances.Add (false, 2);
pm_User = &user;
}
Moves::~Moves ()
{
}
And here we can see that I assign this pointer to the address of the passed in reference of the character object.
Character Header File: Character.h
#pragma once
#include "Moves.h"
#include "ShuffleBag.h"
class Character
{
public:
int m_Health;
int m_Energy;
Moves* pm_Moves;
public:
Character ();
Character (int health, int energy);
~Character ();
};
Likewise, here I have a pointer to a move set for this character. This is because the moves do not have a default constructor.
Character Source File: Character.cpp
#include "Character.h"
Character::Character ()
{
m_Health = 100;
m_Energy = 50;
pm_Moves = &Moves (*this);
}
Character::Character (int health, int energy)
{
m_Health = health;
m_Energy = energy;
pm_Moves = &Moves (*this);
}
Character::~Character ()
{
}
And here I assign this pointer the address of the newly created Moves object. So my question in a TL;DR format is this:
Are my pointers pointing to stack objects and when the classes die, will the pointers themselves? Or will I have to delete them?
You only need to call delete on a pointer that is returned by new. There is no exception to this rule.
In your case though,
pm_Moves = &Moves(*this);
is assigning a pointer to an anonymous temporary Moves(*this);. It's that pointer that's immediately invalided after the statement! The program behaviour on using that pointer for anything is undefined.
So you obviously need to redesign all this. Consider looking at std::unique_ptr when you refactor.
I know that any pointer created with new[] must be deleted with
delete[]
I've seen this confusion over and over again. You don't delete pointers, you delete objects. Or better to understand, if you talk about malloc / free: you don't free pointers, you free memory. The pointer just points to the object(s) / memory you need to delete.
E.g.:
int a = 24; // just an int
int* p1 = new int; // new allocates memory for an int,
// creates an int at that location
// and then returns a pointer to this newly created int
// p1 now points to the newly created int
int* p2 = p1; // p2 now also points to the created int
p1 = a; // p1 now points to a
// what do we delete now? p1?
// no, we don't delete pointers,
// we delete objects dynamically created by new
// what pointer points to those objects?
// at this line it is p2
// so correct is:
delete p2;
There is no new dynamic element created in this class, so you cannot destroy it.

Copying "this" pointer to a buffer

I need to copy the address of this pointer to a buffer and re-typecast it elsewhere. I am aware that I can do it, if I do it outside the class. But,here I specifically need to use some member function as given in the sample code provided here:
#include <iostream>
#include <cstring>
class MyClass
{
public:
MyClass(const int & i)
{
id = i;
}
~MyClass()
{
}
void getAddress(char* address)
{
memcpy(address, this, sizeof(this));
}
void print() const
{
std::cout<<" My id: "<<id<<std::endl;
}
private:
int id;
};
int main()
{
MyClass myClass(100);
std::cout<<"myClass: "<<&myClass<<std::endl;
myClass.print();
// Need to copy the address to a buffer, sepcifically using a function as follows and retrieve it later
char tmp[128];
myClass.getAddress(tmp);
// retreiving the pointer
MyClass* myClassPtr = (MyClass*) tmp;
std::cout<<"myClassPtr: "<<myClassPtr<<std::endl;
myClassPtr->print();
return 0;
}
My Output:
myClass: 0x7fff22d369e0
My id: 100
myClassPtr: 0x7fff22d369f0
My id: 100
As we can see two addresses are different. However, both function are printing the id correctly. I wonder how this happens! I also need the correct method.
Correct version of getAddress():
void getAddress(char* address)
{
const MyClass* tmp = this;
memcpy(address, &tmp, sizeof(this));
}
Update:
// retreiving the pointer
// MyClass* myClassPtr = (MyClass*) tmp; - wrong
MyClass* myClassPtr = *( (MyClass**) tmp );
You are not copying the value of the this pointer, but the data that the pointer is pointing to (memcpy expects the address of the data to copy).
The correct syntax would be:
MyClass* ptr = this;
memcpy(address, &ptr, sizeof(ptr));
That is why you get the same/correct output at the end.
Then, the assignment
MyClass* myClassPtr = (MyClass*) tmp;
is wrong too, you set the pointer to the same address as the char buffer, not to the address that is stored in the char buffer.
A possible solution could look like this:
MyClass* myClassPtr;
memcpy( &myClassPtr, tmp, sizeof( MyClass*));
Finally: I'd like to know what exactly you want to do, that you want to implement something like this? Maybe this is the solution for this problem, but I have a strong feeling that this is the wrong solution for the real problem ...

pointers and references question

#ifndef DELETE
#define DELETE(var) delete var, var = NULL
#endif
using namespace std;
class Teste {
private:
Teste *_Z;
public:
Teste(){
AnyNum = 5;
_Z = NULL;
}
~Teste(){
if (_Z != NULL)
DELETE(_Z);
}
Teste *Z(){
_Z = new Teste;
return _Z;
}
void Z(Teste *value){
value->AnyNum = 100;
*_Z = *value;
}
int AnyNum;
};
int main(int argc, char *argv[]){
Teste *b = new Teste, *a;
a = b->Z();
cout << "a->AnyNum: " << a->AnyNum << "\n";
b->Z(new Teste);
cout << "a->AnyNum: " << a->AnyNum << "\n";
//wdDELETE(a);
DELETE(b);
return 0;
}
I would like to know if there is a memory leak in this code
it works ok, the *a is set twice and the AnyNum prints different numbers on each cout <<
but I wonder what happened to the _Z after the setter(new Teste), I don't have much knowledge in pointers/references yet, but for the logic I guess it is being swapped for the new variable
if it is leaking, is there anyway to accomplish this without having to set a to _Z again?
because the address didn't change, just the direct memory allocated
I was going to use *& instead of just pointers, but would it make difference?
There is a memory leak on this line:
b->Z(new Teste);
because of the definition of the function:
void Z(Teste *value){
value->AnyNum = 100;
*_Z = *value;
}
It looks like Z without arguments was supposed to be a getter and with arguments a setter. I suspect you meant to do:
void Z(Teste *value){
value->AnyNum = 100;
_Z = value;
}
(note the third line) That is, assign the pointer "value" to the pointer "_Z" instead of copy what value pointed at over what Z pointed at. With that, the first memory leak would be resolved, but the code would still have one since _Z could have been holding a pointer. So you'd have to do:
void Z(Teste *value){
value->AnyNum = 100;
delete _Z; // you don't have to check for null
_Z = value;
}
As mentioned in another comment, the real solution is to use smart pointers. Here's a more modern approach to the same code:
using namespace std;
class Teste {
private:
boost::shared_ptr<Teste> Z_;
public:
Teste() : AnyNum(5), Z_(NULL)
{ }
boost::shared_ptr<Teste> Z()
{
Z_.reset(new Teste);
return Z_;
}
void Z(boost::shared_ptr<Teste> value)
{
value->AnyNum = 100;
Z_ = value;
}
int AnyNum;
};
int main(int argc, char *argv[]){
boost::shared_ptr<Teste> b = new Teste, a;
a = b->Z();
cout << "a->AnyNum: " << a->AnyNum << "\n";
b->Z(boost::shared_ptr<Teste>(new Teste));
cout << "a->AnyNum: " << a->AnyNum << "\n";
return 0;
}
Yes there is:
void Z(Teste *value)
{
value->AnyNum = 100;
*_Z = *value; // you need assignment operator
}
The compiler-generated assignment operator will not make a deep copy, instead it will make a shallow copy. What you have to do is to write a suitable assignment operator (and possibly a copy constructor) for Teste. Also, you don't have to check if a pointer is NULL before deleting it:
~Teste()
{
// no need for checking. Nothing will happen if you delete a NULL pointer
if (_Z != NULL)
DELETE(_Z);
}
You've got another problem: _Z is not an identifier you should be using. In general, it's best to avoid leading underscores, and in particular double underscores or underscores followed by a capital letter are reserved for the implementation.
What a mess!
The whole program is very hard to read because of the choice of identifier names to start with:
#ifndef DELETE
#define DELETE(var) delete var, var = NULL
#endif
I find that very ugly.
When using classes it seems very un-nessacery. You could use it where a variables is going out of scope but it is a waster of time in the destructor. I think it would be asier to wrap the code in some smart pointer:
class Teste
{
private:
Teste *_Z;
public:
Teste()
~Teste() // Delete the _Z pointer.
Teste *Z();
void Z(Teste *value);
};
Ok. You have a pointer member that you delete in the destructor.
This means you are taking ownership of the pointer. This means that the ule of four applies (similar to the rule of three but applicable to ownership rules). This means you basically need to write 4 methods or the compiler generated versions will mess up your code. The methods you should write are:
A Normal (or default constructor)
A Copy constructor
An Assignment operator
A destructor.
Your code only has two of these. You need to write the other two.
Or your object should not take ownership of the RAW pointer. ie. use a Smart Pointer.
Teste *_Z;
This is not allowed.
Identifiers beginning with an underscore and a capitol letter are reserved.
You run the risk of an OS macro messing up your code. Stop using an underscore as the first character of identifiers.
~Teste(){
if (_Z != NULL)
DELETE(_Z);
}
This is not needed. Asimple delete _Z would have been fine.
_Z is going out of scope because it is in the destructor so no need to set it to NULL.
The delete operator handles NULL pointers just fine.
~Test()
{ delete _Z;
}
Teste *Z(){
_Z = new Teste;
return _Z;
}
What happens if you call Z() multiple times (PS putting the * next to the Z rather than next to the Teste make it hard to read).
Each time you call Z() the member variable _Z is given a new value. But what happens to the old value? Basically you are leaking it. Also by returning a pointer to an object owned
inside Teste you are giving somebody else the opportunity to abuse the object (delete it etc). This is not good. There is no clear ownership indicated by this method.
Teste& Z()
{
delete _Z; // Destroy the old value
_Z = new Teste; // Allocate a new value.
return *_Z; // Return a reference. This indicates you are retaining ownership.
// Thus any user is not allowed to delete it.
// Also you should note in the docs that it is only valid
// until the next not const call on the object
}
void Z(Teste *value){
value->AnyNum = 100;
*_Z = *value;
}
You are copying the content of a newly constructed object (that contains a pointer) into another dynamically created object!
What happens if _Z had not been allocated first. The constructor sets it to NULL so there is no guarantee that it has a valid value.
Any object you allocate you should also delete. But here value is dynamically allocated passed into Z but never freed. The reason you get away with this is because the pointer is c
opied into _Z and _Z is deleted when its destructor is destroyed.
Teste *b = new Teste, *a;
That's really heard to read. Don;t be lazy write it out properly.
This is considered bad style and you would never get past any code review with that.
Teste* b = new Teste;
Teste* a; // Why not set it to NULL
a = b->Z();
Getting ab object for a. But who was destroying the object a or b?
b->Z(new Teste);
It just gets too convoluted after that.
(I tried to add this as a comment but that screws up the code..)
I'd aslo strongly suggest not to use
#ifndef DELETE
#define DELETE(var) delete var, var = NULL
#endif
but instead something like
struct Deleter
{
template< class tType >
void operator() ( tType*& p )
{
delete p;
p = 0;
}
};
usage:
Deleter()( somePointerToDeleteAndSetToZero );
(not really an answer, but a comment wouldn't do)
The way you defined your macro is prone to a subtle errors (and the fact that no one spotted it so far just proves it). Consider your code:
if (_Z != NULL) // yes, this check is not needed, but that's not the point I'm trying to make
DELETE(_Z);
What happens after the preprocessor pass:
if (_Z != 0)
delete _Z; _Z = 0;
If you still have trouble seeing it, let me indent it properly:
if (_Z != 0)
delete _Z;
_Z = 0;
It's not a big deal, given that particular if condition, but it will blow-up with anything else and you will spend ages trying to figure out why your pointers are suddenly NULL. That's why inline functions are preferred to macros - it's more difficult to mess them up.
Edit: ok, you used comma in your macro definition so you are safe... but I would still say it's safer to use [inline] function in this case. I'm not one of the do-not-use-macros-ever guys, but I wouldn't use them unless they are strictly necessary and they are not in this case
void Z(Teste *value){
value->AnyNum = 100;
*_Z = *value;
}
and
b->Z(new Teste);
creates a memory leak
the 'new Teste' never gets deleted, instead what you are doing is allocating a new object as parameter, then copying whatever is in there using *_Z = *value but the object is not deleted after the call.
if you were to write
Test* param - new Teste;
b->Z(param)
delete param;
it would be better
of course most would use boost::shared_ptr or something similar to avoid caring about delete and such