I am experimenting with Struct, pointers and typedef in the code below. I want to create a pointer to a struct that I made up. Then I want to manipulate the struct's members using the -> operator.
The below code compiles fine, however, when I run the program it produces a segmentation fault.
Can someone please help explain where my logic went wrong?
Thank you.
struct Structure1 {
char c;
int i;
float f;
double d;
};
typedef Structure1* structp;
int main(){
structp s1, s2;
s1->c = 'a';
s1->i = 1;
s1->f = 3.14;
s1->d = 0.00093;
s2->c = 'a';
s2->i = 1;
s2->f = 3.14;
s2->d = 0.00093;
}
structp s1, s2;
You've declared two pointers, s1 and s2 but they don't point anywhere yet! You need to allocate memory for these pointers using new.
s1 = new Structure1();
s1->c = 'a';
s1->i = 1;
// ...
Don't forget to delete the memory afterwards:
delete s1;
See this answer why the parentheses in new Structure1() make a difference. Also, note that there are other ways to obtain a pointer to an object, such as using the & operator, but in this particular case, I think you want to allocate memory.
Pointers are objects in memory that point to another object. When using the indirection operator it causes the pointer to be dereferenced. For example, this:
s1->c;
is the same as:
(*s1).c;
When you dereference a pointer, it returns a reference to the object that it points to. If there is no object that it points to (or it points to nullptr), deferencing it gives your program Undefined Behavior.
The solution would be to create a new instance of a class on the heap and return a pointer to it. That is what new does:
Structure1 *structp = new Structure1();
It makes sense once you realize that pointers are not the actual objects, they are simply memory addresses. If you don't allocate space or assign to it a memory address, it will remain uninitialized and filled in with garbage. Just like a regular object, why would you want to use an initialized pointer?
Related
board *gameBoard = new board(givenX,givenY,givenMineCount);
I know that the above statement declares an object pointer that points to board.
But I'm wondering what the statement below means.
board gameBoard = *new board(givenX,givenY,givenMineCount);
In both statements the "new" keyword returns a pointer to the object you are allocating. The reason the second statement works is because if you put a * before a pointer you dereference that pointer which, in simple terms, gives you the object the pointer is pointing to. But as Mooing Duck said if you don't understand this you should avoid the new keyword all together.
Edit: to answer what it means? it means you allocate a board object then dereference it and save a new copy in your variable gameBoard. Essentially giving you two copies of the Board object.
new board(givenX,givenY,givenMineCount); in a nutshell, performs two things: creates a board object in memory and returns the address where it was created.
In your second statement, gameBoard is a stack variable that holds a board object. As I mentioned before, the new returns an address and by using the * operator, you're basically "interpreting" (the actual technical term is dereferencing) the address as a board. That said, doing this seems to be making a copy and assigning it to boardGame and leave lingering in memory what was created with new.
I'm new to c++, but I think extra details are missing here for beginners like me and like the asker.
Note: This answer contains details for newbies like me.. advanced c++ developers may find this post somewhat confusing!
Lazy? tl;dr at the end
Does always creating and object with *new creates two copies of objects? (one will never ever be deleted)
Lets check this out:
As explained by others, the *new is just a shortcut to new in one statement and then dereference it with the asterisk operator (*)
Consider the following struct that holds a single number:
struct myStruct
{
public:
myStruct() { innerNumber = 0; }
myStruct(uint16_t num) {
innerNumber = num;
}
uint16_t innerNumber;
};
Lets create a SINGLE object, and dereference it MULTIPLE times:
myStruct* obj = new myStruct();
myStruct obj1 = *obj;
myStruct obj2 = *obj;
myStruct obj3 = *obj;
obj1.innerNumber = 1;
obj2.innerNumber = 2;
obj3.innerNumber = 3;
printf("%d-%d-%d\n", obj1.innerNumber, obj2.innerNumber, obj3.innerNumber);
prints: 1-2-3
Pretty cool =] (and dangerous)
So, if we get it correctly, it is ALWAYS a bad idea to use *new as already mentioned here, it will always cause a memory leak!!
lets see it in action:
while (true) {
myStruct& inner = *new myStruct();
delete &inner;
}
That code should:
enter an infinite while loop
allocate a new myStruct object
dereference it (causing it to be copied!)
delete the copy only
Or in shortly: A MEMORY LEAK
Well, I'm running this, and the memory isn't increasing!
*new is GOOD when creating a reference. You can see that I defined
a ref type by the & operator (myStruct& inner)
Another problem that may arise (and is general for references) is that:
// Create a reference
myStruct& inner = *new myStruct();
inner.innerNumber = 0;
// WHAT WILL HAPPEN HERE?
myStruct whatAmI1 = inner;
myStruct whatAmI2 = inner;
whatAmI1.innerNumber = 1;
whatAmI2.innerNumber = 2;
printf("Original: %d Copies: %d-%d\n", inner.innerNumber, whatAmI1.innerNumber, whatAmI2.innerNumber);
prints: Original: 0 Copies: 1-2
dangerous!
TL;DR
*new is bad for creating value types
*new is good for creating reference type
Be careful when assigning a reference type to a value variable, it
makes a copy
I have the following simple code, and I have not found a thread where smart pointers are used for this simple case, but rather copy objects:
int main()
{
int i = 1;
std::unique_ptr<int> p1(&i);
*p1 = 2;
return 0;
}
This results in _BLOCK_TYPE_IS_INVALID when the pointer goes out of scope. If I call p1.release(), the code works fine and I do not get this error. I thought such pointers are smart enough to handle dangling pointers?
An alternative would be if I had a copy of i, which does not give the above error:
std::unique_ptr<int> p1(new int(i));
What is the advantage of using smart pointers here, where I do not want to perform the local copy?
If I were to use a raw pointer:
int i = 1;
int *p1 = &i;
*p1 = 2;
I would not get an error, even if I don't code:
p1 = nullptr;
std::unique_ptrs are for handling dynamically allocated memory; they're said to take ownership of the pointer when you construct one.
Your int i; is on the stack, and thus isn't dynamically allocated; it's ownership can't be taken away from the stack. When the unique_ptr destructor tries to delete the pointer you gave it (because it thinks nobody owns it anymore), you get that error because delete can only be used for pointers created with new.
Given your short example, I don't know what context this is in... But you should use raw pointers (or make a copy, as you said) for stack-allocated variables.
The answer provided by #qzx is the main reason of the problem you've reported in your code
One additional thing about std::unique_ptr<> usage. You should always try to use std::make_unique<>() to create a std::unique_ptr. It sometimes help in using this pointer appropriately by providing appropriate compilation errors.
For example, if you change the above code with std::make_unique<> as
int i = 1;
std::unique_ptr<int> p1 = make_unique<int>(&i);
then most compiler will give error as
can't convert int* to int
It will help you to use a copy which creates a totally new integer whose ownership is taken by std::unique_ptr<>
int i = 1;
std::unique_ptr<int> p1 = make_unique<int>(i);
*p1 = 2;
This code works.
I have noticed that if i create a pointer in a function, it won't let me set a value to it.
for example:
int func() {
int* pointer;
*pointer = 0 //error I get: "Exception: STATUS_ACCESS_VIOLATION"
return *pointer;
}
I get that not letting you set a pointer in the function because if I use a normal int it works:
int func() {
int notAPointer;
notAPointer = 0;
return notAPointer;
}
Can anyone explain to me why that is?
You haven't assigned any memory for your pointer to point to.
That means that dereferencing the pointer (*pointer) causes undefined behavior (like a crash in your case). You need to initialize the pointer before dereferencing it:
int* pointer = new int;
(And afterwards, delete pointer; to not leak the memory. Always delete everything you get from new.)
Also, pointers don't have to point to dynamically allocated data (acquired by a call to new), you can point to automatic (stack) variables too:
int func() {
int valueOnStack = 42;
int* pointer = &valueOnStack;
*pointer = 0;
return *pointer;
}
Because when you declare pointer it is pointing to a completely arbitrary memory location. You can't just write to any old piece of memory.
You need to allocate memory for it first:
int* pointer = new int;
*pointer = 0;
Or just:
int* pointer = new int();
The pointer pointer is uninitialized and points to a random location in memory when you declare it. It could be pointing into the system stack, or the global variables, or into the program's code space, or into the operating system. When you say *pointer = 0;, the program will simply try to write a 0 to whatever random location pointer points to.
The program may explode immediately, or may wait half an hour and then explode, or it may subtly corrupt data in another part of your program and you may never realize it. This can make this error very hard to track down. Make sure you initialize all pointers to a valid address before dereferencing them.
pointer does not point to anything following int* pointer;
So the behaviour of dereferencing it is undefined.
If you'd written
int n;
pointer = &n;
then you could dereference it.
Altenatively, you can allocate memory to it from the heap:
pointer = new int;
But you must remember to call delete pointer; else you'll leak memory.
This code is completely valid inside a function:
int *pointer = 0;
BUT, it would be the same as setting a pointer to the NULL macro.
If you try to set another value the compiler is going to complain that there is no valid conversion from int to int*:
int *pointer = 1; // Error
However, if you want to assign a value to the pointer, follow TartanLlama's answer using new and delete. Allocate memory first and then assign a value:
int *pointer = new int;
*pointer = 1; // OK
// delete when appropriate
Consider the sample code below. The class Data is used to store an array of data: for simplicity, I chose to use a vector<char> as data member. However, these data must be processed by an external routine, which requires a pointer to the first element of the array and, of course, the length of this array: for this reason, I have also implemented the functions get_data() and get_length().
class Data
{
public:
Data(const char* sourcePtr, int sourceLength) : _data(sourcePtr, sourcePtr+sourceLength) { ; }
const char* get_data() const { return &_data.front(); }
int get_length() const { return _data.size(); }
void print() const
{
vector<char>::const_iterator it;
for(it = _data.begin(); it != _data.end(); ++it)
cout << *it;
}
private:
vector<char> _data;
};
Now consider the following code sample, which uses the class Data.
int main(int argc, char** argv)
{
char* a = new char[4];
a[0] = 'b';
a[1] = 'y';
a[2] = 't';
a[3] = 'e';
Data myData(a,4);
delete[] a;
myData.print();
cout << endl;
const char* aPtr = myData.get_data();
// The following statement frees the memory allocated
// for the data member of the class Data.
delete[] aPtr;
return 0;
}
The above statement delete[] aPtr frees the memory allocated for the data member of the class Data. As a consequence, when the myData object is deallocated automatically, the content of the vector<char> has already been deallocated manually, and obviously an error SIGABRT occurs.
How to ensure that the compiler signals the statement delete[] aPtr as an error? How should you modify the class Data to achieve this goal?
The most straightforward way to deal with this is to make sure that it is clear who is the "owner" of a pointer. In my C++ days, if a pointer was returned by a function, the function's name should start with "Create" rather than "Get". Later, we usually returned smart pointers, in such a scenario.
It is in fact not at all hard to write C++ where you never need to delete any pointer explicitly, but rather store all of them in a smart pointer that will delete the pointee when it gets destroyed itself.
Stop using "naked" new and delete operations, wrap the new in an RAII type and do not use delete unless you're writing a destructor of an RAII type.
std::unique_ptr<char[]> a{ new char[4] };
a[0] = 'b';
a[1] = 'y';
a[2] = 't';
a[3] = 'e';
Data myData(std::move(a),4);
This code means that ownership of the array is clearly given to the smart pointer, and then clearly transferred to the Data object. Attempting to delete the array will not compile.
This doesn't prevent users later doing delete[] aPtr but if you get into the habit of never using delete except in the destructor of an RAII type, then it becomes glaringly obvious when someone introduces a bug by using delete somewhere they shouldn't, because they don't own the memory.
Stop fiddling about with bare pointers. If users of your code won't stop doing so then let them learn the hard way.
You don't. new and delete don't track who owns the pointer. That's your job.
What you can do instead is make a copy of the data the pointer points to. Then it doesn't matter what the caller does with its array. You have your own copy, and assuming you're not doing something braindead like exposing it to anyone who wants it, it's safe.
Or, check out std::unique_ptr and std::shared_ptr. :P They're the new hotness as far as memory management is concerned; when you use a smart pointer, memory very nearly manages itself.
Write good documentation. It's not your job to prevent other programmers from doing stupid things.
I'm bit new to C++ and try to work things with Qt and came across this confusing thing:
The concepts on various tutorials state something like:
Class *obj;
*obj - will display the value of object stored at the referenced memory
obj - will be address of memory to which it is pointing
so, I would do something like
*obj=new Class();
but if I want to access a function, I have to do obj->function1();
instead of *obj->function1();
-- not sure why, since with normal objects [ normalObj.function1();] would work, since that's the value directly.
So, for pointer objects why do we use memory reference to access the function,
or is it that in case of normal objects also, its always references
P.S: Can someone guide me to a good tutorial of usage of pointers in C++, so that my queries like these can be directly addressed in it.
The * symbol is used to define a pointer and to dereference a pointer. For example, if I wanted to create a pointer to an int, I could do:
int *ptr;
In this example, the * is being used to declare that this is a pointer to an int. Now, when you are not declaring a pointer and you use the * symbol with an already declared pointer, then you are dereferencing it. As you probably know, a pointer is simply an address. When you dereference a pointer, you are obtaining the value that is being pointed to by that address. For example:
int pointToMe = 5;
int *ptr = &pointToMe;
std::cout << *ptr;
This will print out 5. Also, if you are assigning a pointer to a new address and it's not in the declaration, you do not use the * symbol. So:
int pointToMe = 5;
int *ptr;
ptr = &pointToMe;
is how you would do it. You can also deference the pointer to assign a new value to the value being pointed to by the address. Such as:
int pointToMe = 5;
int *ptr = &pointToMe;
std::cout << *ptr; // Prints out 5
*ptr = 27;
std::cout << *ptr; // Prints out 27
Now, -> acts like the deference symbol. It will dereference the pointer and then use the member functions and variables as if you had used . with a non-pointer object. Even with an object that is not a pointer you can use the -> by first getting the address:
CObj object;
(&object)->MemberFunction();
That's just a brief overview of pointers, hope it helps.
You can use the "normal" . to access the objects members, but you have to dereference the pointer first.
Due to operator precedence, this will look like (*obj).member. For those who think this is too much to write, obj->member is a shorter alternative.
If you have an object c of type Class, *c.ptr means dereferencing a pointer ptr that is a member of Class. That is one reason for (*obj).member, which means something else.
Actually, you're wrong. You do:
obj=new Class();
or
Class *obj = new Class;
which are completely different.
Class *obj;
*obj = new Class;
wouldn't compile.
obj is of type Class*, so that's what you can assign to it (and what new Class returns).
More precisely u can do like this
Class obj;
Class* obj_ptr;
obj_ptr = &obj;
// Now onwards you can use the pointer to access data members and function
obj_ptr->a = 10; // Like this