Help with first C++ class/pointers - c++

Hey guys, I taught myself PHP a few years back and am now in college and am relatively well versed in Java (and by that I really mean I'm a beginner but did my data structures course in it. I'll be taking Algorithms next semester)
In any case...I want to learn C++ and stumbled upon this:
http://newdata.box.sk/bx/c/
What is really tripping me up right now is pointers...I THINK I get the theory but a really simple "program" isn't running right. It compiles but then there's a memory error.
I've decided to purchase C++ Primer after doing a few searches here on SO so it'll get here on Friday. Until then, can anyone tell me what is (horribly) wrong with this simple code:
class Number {
public:
string *owner;
int getNum() {
return *num;
}
int getTwice() {
return *twice;
}
Number(int our_num, string me) {
*num = our_num;
*twice = 2 * *num;
*owner = me;
}
private:
int *num;
int *twice;
};
int main()
{
Number *nbr3 = new Number(3,"Bob");
cout << nbr3->getNum() << endl;
cout << nbr3->getTwice() << endl;
cout << nbr3->owner << endl;
delete nbr3;
system("PAUSE");
return 0;
}
The errors appear in the constructor...like the *num=our_num part.
But isn't that line saying "set the value of the num pointer to our_num"? That IS what I want!
Thanks for helping with what I know to be a very silly and fundamental error...

You didn't allocate memory locations to point to for num, twice,owner. So, in your constructor -
Number(int our_num, string me) {
num = new int;
twice = new int;
owner = new string;
*num = our_num;
*twice = 2 * (*num);
*owner = me;
}
Since, the class is managing resources, class Number should follow -Rule of Three
Edit 1
Pointers are like any other variables but holds a memory address. Just declaring int* ptr; doesn't mean that ptr is pointing a to valid memory location right away. You should assign/initialize it to where it should point to.
So,
int *ptr;
int num = 10;
ptr = &num; // ptr points to num location
int *ptr2 = new int; // The operator returns a memory location from free store that can hold an integer.
*ptr2 = 10; // Now, store 10 in the location ptr2 is pointing to.
// ......
delete ptr2; // You should return the resources back to the free store since we are managing resources.
Hope it helps to an extent.

This is the problem:
Number(int our_num, string me) {
*num = our_num;
*twice = 2 * *num;
*owner = me;
}
private:
int *num;
int *twice;
In your class you have declared num and twice to be pointers, but they do not point
to anything. Doing *num = our_num doesn't change the pointer instead what that means is that you are derefencing what num is pointing to in order to assign the value contained in our_num. This will cause a crash since num is some random value.
In order to fix this set the pointer to point to an int first.
e.g
int myints[2];
num = myints
twice = myints+1;
then you can do
*num = our_num
so when you write
int *num; you are telling the compiler that num will contain an address.
when you use num you are in fact handling the address.
when you write *num you are referencing the data that is at the address num.

num and twice don't point to anything. In the constructor of the class you need num=new int and twice=new int, and in the destructor you need to delete them

Related

c++ pointer to function and void pointers iteraction resulting in wierd things

Im making a little project at home about genetic algorithm. But im trying to make it generic, so i use pointers to function and void pointers. but i think it might be making some problems.
The main goal of this section of the project is to get a pointer to a function, which return a certain struct. The struct containing a void pointer
and when im trying to view the value of where it points too it isn`t quite right.I suspect that maybe the interaction between these two might be causing me some problems.
details:
struct:
struct dna_s{
int size;
void *dna;
};
population is a class contaning all the population for the process. besides, it contains 2 functions as well, init_func and fitter_func which are both pointers to functions.
pointer to function definition:
typedef dna_s (*init_func_t)();
typedef int (*fitter_func_t)(dna_s);
population class:
class population{
private:
// Parameters
int population_size;
node *pop_nodes;
// Functions
init_func_t init_func;
fitter_func_t fitter_func;
public:
population(int pop_size,init_func_t initialization_func){
// Insert parameters into vars.
this->population_size = pop_size;
this->init_func = initialization_func;
// Create new node array.
this->pop_nodes = new node[this->population_size];
for(int i = 0;i < this->population_size; i++){
dna_s curr_dna = this->init_func();
char *s = static_cast<char*>(curr_dna.dna);
cout << s << endl;
this->pop_nodes[i].update_dna(curr_dna);
}
}
};
You can see that in the constructor im inserting a pointer to function, init_func. this function is generating random words.
init_func:
dna_s init_func(){
string alphanum = "0123456789!##$%^&*ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char init_s[STRING_SIZE+1] = {};
dna_s dna;
// Generate String
for(int i = 0; i < STRING_SIZE; i++){
init_s[i] = alphanum[rand() % alphanum.size()];
}
cout << "-->" << init_s << endl;
// Insert into struct.
dna.size = STRING_SIZE;
dna.dna = static_cast<void*>(&init_s);
// Return it
return dna;
}
the main function is not so interesting but it might be connected:
int main(){
// Init srand
srand(time(0));
// Parameters
int population_size = 10;
population pop(population_size, init_func);
}
now for the interesting part, whats the problem?
in the init_func the cout prints:
-->e%wfF
which is all good
but in the population class the cout prints:
e%Ω²(
and the wierd thing is the first 2 characters will always be the same, but the other 3 will always be this string Ω²(.
example:
-->XaYN7
XaΩ²(
-->oBK9Q
oBΩ²(
-->lf!KF
lfΩ²(
-->RZqMm
RZΩ²(
-->oNhMC
oNΩ²(
-->EGB6m
EGΩ²(
-->osafQ
osΩ²(
-->3#NQt
3#Ω²(
-->D62l0
D6Ω²(
-->tV#mu
tVΩ²(
Your code has a few lifetime issues. In your dna_S struct:
void *dna;
This is a pointer, it points to an object that exists elsewhere. Then, in your init_func:
dna_s init_func(){
...
char init_s[STRING_SIZE+1] = {};
dna_s dna;
...
dna.dna = static_cast<void*>(&init_s);
...
return dna;
}
init_s is a variable that exists inside init_func, you make dna point to that variable and then leave the function. init_s ceases to exist at this point, dna is pointing nowhere useful when the population constructor gets it, causing undefined behavior.
You could work around that by allocating memory with new char[], like you did for pop_nodes, but you are responsible for deleting that memory when it is no longer used.

Why one of those two similar functions crashes and one works ok?

This is really weird. If I increase the value of asize just by one crashSystem() does what its name speaks. Second function returning an int pointer works ok with much bigger values. Those two functions just delete and allocate the same dynamic array with same size (I created it just for test purposes).
Note: I think it could have something to do with maximum stack capacity 1MB (130037 * 8 in bytes is near 1MB), but it's really strange 'cause allocating using new inside function should work the same as any other new.
Using Visual Studio 2015
#include <iostream>
void crashSystem(int * dynamicArray, int asize) {
delete[] dynamicArray;
//dynamicArray = nullptr; does not matter at all
dynamicArray = new int[asize];
std::cout << "mem allocated\n";
}
int * worksOk(int * dynamicArray, int asize) {
int * newDynamicArray = new int[asize];
delete[] dynamicArray;
std::cout << "mem allocated\n";
return newDynamicArray;
}
int main()
{
int asize = 130037; // dynamic array size
//asize = 12330037; // for testing second function that works
int * dynamicArray;
dynamicArray = new int[asize];
for (int i = 0; i < 100; i++)
{
std::cout << "iteration " << i << " ";
crashSystem(dynamicArray, asize);
//dynamicArray = worksOk(dynamicArray, asize);
}
std::cout << "\n";
system("PAUSE");
}
Note 2: Crashing app this way in Release mode tends to block executable by creating non existent process (checked with Process Hacker 2)
The problem is that you're passing pointer by value, so it still points to the new int[asize]; allocated in main(), on which you then call multiple delete [].
It becomes a dangling pointer after the first delete [] call.
Even assigning nullptr won't help you if the pointer is not being passed by reference.
worksOk works, because you're returning the pointer pointing to the newly allocated space and assigning it, so it's valid every time.
Just change the signature so it uses reference:
void crashSystem(int *&dynamicArray, int asize)
and it should work fine.

Adding element to array of struct c++

Can someone explain why this code does not work? It keeps crashing when it asks for input in addCar().
I think something is wrong with copying an array, but I can't figure out what exactly. I also tried to use copy() but it didn't work either.
#include <iostream>
#include <string>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
struct Car{
string Brand;
string model;
long mileage;
};
void addCar(int *ptr, struct Car *arra){
*ptr=*ptr+1;
Car *newArr = new Car[*ptr];
memcpy(newArr, arra, (*ptr)*sizeof(Car));
cout<<"Brand ";
getline(cin,newArr[*ptr].Brand);
cout<<"Model ";
getline(cin, newArr[*ptr].model);
cout<<"mileage ";
cin>>newArr[*ptr].mileage;
arra=newArr;
};
int main(int argc, char** argv) {
int size=1;
int *ptr_size;
ptr_size=&size;
Car *tab=new Car[*ptr_size];
tab[0].Brand = "Audi";
tab[0].model = "A8";
tab[0].mileage = 14366;
addCar(*ptr_size, tab);
return 0;
}
The fail is probably here:
getline(cin,newArr[*ptr].Brand);
A bit above, you did this: *ptr=*ptr+1; and made newArr an array of *ptr elements. Arrays are origin zero. That means the first item in the array is newArr[0]. The last will be at newArr[*ptr-1], so writing into newArr[*ptr] is writing over someone else's memory. Generally a bad thing to do.
But this is also not cool:
*ptr=*ptr+1;
Car *newArr = new Car[size+1];
memcpy(newArr, arra, (*ptr)*sizeof(Car));
You increment the size of the array. That's OK.
You create a new array with the new size. That's OK.
You copy new size number of elements from the old array to the new array and over shoot the end of the old array. Not OK.
The best answer is given by Jerry Coffin and Paul McKenzie in the comments: use a std::vector. If this is not allowed... Ick.
But alrighty then.
First, memcpy literally copies a block of memory. It does not know or care what that block of memory is or what it contains. Never use memcpy unless you are copying something really, really simple like basic data type or a structure made up of nothing but basic data types. String is not basic. The data represented by a string might not be inside the string. In that case, you copy a pointer to the string and that pointer will not be valid after the death of the string. That's not a problem in your case because you don't kill the string. That leads to problem 2. Let's fix that before you get there. The easiest way (other than vector) is going to be:
for (int index = 0; index < *ptr-1; index++)
{
newArr[index] = arra[index];
}
An optimization note. You don't want to resize and copy the array every time you add to it. Consider having two integers, one size of array and the other index into array and double the size of the array every time the index is about to catch up with the size.
When you allocate any memory for data with new somebody has to clean up and put that memory back with delete. In C++ that somebody is you. so, before you arra=newArr; you need to delete[] arra;
Passing in the array index as a pointer overcomplicates. Use a reference or just pass by value and return the new index. Also, don't name a variable ptr. Use something descriptive.
void addCar(int &arrasize, struct Car *arra){
or
int addCar(int arrasize, struct Car *arra){
Next problem: int addCar(int arrasize, struct Car *arra){ passes in a pointer to arra. But you passed the pointer by value, made a copy of the pointer, so when you change the pointer inside the function, it's only the copy that got changed and the new array is not going to come back out again. So,
int addCar(int arrasize, struct Car * & arra){
Passes in a reference to the pointer and allows you to modify the pointer inside the function.
Putting all that together:
int addCar(int size, struct Car * & arra)
{
Car *newArr = new Car[size + 1];
for (int index = 0; index < size; index++)
{
newArr[index] = arra[index];
}
cout << "Brand ";
getline(cin, newArr[size].Brand);
cout << "Model ";
getline(cin, newArr[size].model);
cout << "mileage ";
cin >> newArr[size].mileage;
delete[] arra;
arra = newArr;
return size+1;
}
int main()
{
int size=1;
Car *tab=new Car[size];
tab[0].Brand = "Audi";
tab[0].model = "A8";
tab[0].mileage = 14366;
size = addCar(size, tab);
// do more stuff;
// bit of test code here
for (int index = 0; index < size; index++)
{
cout << "Car " << index << " brand =" <<tab[index].Brand << " Model=" << tab[index].model << " mileage=" <<tab[index].mileage << endl;
}
delete[] tab;
return 0;
}
When you are copying the old array to the new one you are accessing invalid memory, remember that, in that point, arra has size *ptr-1 not *ptr, so the line should be
memcpy(newArr, arra, (*ptr-1)*sizeof(Car));
also in the other lines you should insert the new value in the *ptr-1 position because the indexes in newArr go from 0 to size-1 ie *ptr-1:
cout<<"Brand ";
getline(cin,newArr[*ptr-1].Brand);
cout<<"Model ";
getline(cin, newArr[*ptr-1].model);
cout<<"mileage ";
cin>>newArr[*ptr-1].mileage;

C++ problems with pointers while creating Nodes

So I was trying to convert a BST to DLL using some given functions which I had to use. While doing that, I kept getting segmentation faults. As I tried debugging it, I finally came to this. I have written a very simple test script below.
What I knew about pointers is it is passed by reference, as in if I am changing the value/object to which the passed pointer points to, it is reflected in my original calling function.
Why is it that when I create a new Node and then pass the pointer (myf), it works, but when I just pass the pointer and create the new Node inside the function, it shows segmentation fault (myf2)?
If this is because the new node goes out of scope, check the function "myf" again. I have created a new Node which is pointed to by my original node. And the value of this is retained after the function call ends. Doesn't this too go out of scope then?
I have some basic fundamental problems with pointers it appears and this would really help. Thanks
#include<iostream>
using namespace std;
class Node
{
public:
int val;
Node *left;
};
void myf(Node *a)
{
a->left = new Node();
a->left->val = 20;
a->val = 15;
}
void myf2(Node *a)
{
a = new Node();
a->val = 35;
}
int main()
{
Node *a = NULL, *b = NULL;
a = new Node();
a->val = 5;
myf(a);
cout << "New value of a = " << a->val << endl;
cout << "left value of a = " << a->left->val << endl;
myf2(b);
cout << "New value of b = " << b->val << endl;
}
Your problem is, your pointer isn't being set to b, to do so, you'd need to edit myf2 to something like this:
void myf2(Node **a)
{
*a = new Node();
(*a)->val=35;
}
And call myf2 like so:
myf2(&b);
And that should solve your problem, I believe.
Don't think of Node *b as only a pointer, think of it as an integer as well, because that's what a pointer breaks down to, an integer pointing to a space in memory.
So you pass a pointer of the pointer(an integer) to the function.
Another example would be:
void myfunction(int *i) {
*i = 5;
}
int main(int argc, char** argv) {
int x;
myfunction(&x);
cout << x << endl;
return 0;
}
But that's using an actual integer.
Why is it that when I create a new Node and then pass the pointer (myf), it works,
Node *a:
main() makes it point it to a block of memory, you pass that address to myf, you update the memory in that block. It works!
But when I just pass the pointer and create the new Node inside the function, it shows segmentation fault (myf2)?
Node *b:
main() doesn't assign it anything, it is pointing to NULL, myf2() get just the address that is NULL, you create another pointer b (not the same as that in main() ), make it points to some block of memory, but it doesn't update what your original b in main() points to, which is still pointing to NULL. Hence SEGFAULT.
Essentially you are trying two different valid approaches, this is the right way:
Case 1.
main()
{
Node* a = NULL;
a = new Node(); //make 'a' point to some valid block of memory
myf(a); // here you are passing the address of the memory block of type Node
cout << "New value of a = " << a->val << endl; //and this is valid since 'a' points to a valid address
}
void myf(Node *a)
{
a->left = new Node();
a->left->val = 20; // Since the address that you got here is valid, you can make changes here, and in main() Node* a is aware of this address
a->val = 15;
}
Case 2.
main()
{
Node* b = NULL;
myf2(&b); // here since b points to NULL, you have to send the address where this NULL is stored so that the called functon can upadte this NULL to something meaningful
cout << "New value of b = " << b->val << endl; // this is correct, because we changed what 'b' pointed to from NULL to a valid block of memory of type 'Node'
}
void myf2(Node **a) //It is a double pointer here because you need to update what it points to, curently it holds NULL
{
*a = new Node(); // Make it point to a valid address, remember main() has track of 'a',
*a->val = 35; // Now if you make any changes to the blok that 'a' points to, main() will have account of it
}
You need to return the reference of Node *a to which you have dynamically allocated memory..
Node* myf(Node *a)
{
a->left = new Node();
a->left->val=20;
a->val=15;
return a;
}
In main ()
a = myf(a);
previously a in main() is not pointing to memory allocated in myf() function...
Receive your Node ptr by reference as below..
void myf2(Node *&a) //<-- Notice & in function signature.
In your current code, you are passing a (Node*) by value, so, whatever changes done in the function will not reflect outside of function and accessing b->val (null ptr access) will be a segment fault

Stack memory allocation

It is being said that local variable will be allocated and deallocated automatically when function ends in C/C++.
According to my understanding, when having been deallocated, the value held by local variable also be destroyed!!! Please correct me if i'm wrong
Consider following code:
void doSomething(int** num)
{
int a = 10;
*num = &a;
} // end of function and a will be destroyed
void main()
{
int* number;
doSomething(&number);
cout << *number << endl; // print 10 ???
}
Could anybody clarify for me?
You are correct. your cout may or may NOT print 10. It will invoke undefined behavior.
To make a bit more of a note, try running the following code under your compiler with no optimizations enabled.
#include <iostream>
using namespace std;
void doSomething(int** num)
{
int a = 10;
*num = &a;
}
void doSomethingElse() {
int x = 20;
}
int main()
{
int* number;
doSomething(&number);
doSomethingElse();
cout << *number << endl; // This will probably print 20!
}
In this case, the integer a is on the stack. You are returning the address of that variable to the main program. The value at that address location after the call is undefined. It is possible in some situations that it could print 10 if that portion of the stack was not overwritten (but you certainly would not want to rely on it).
The content of the memory isn't actually destroyed.
For this case, num will point to a location which isn't being allocated for any variable, but it will hold it's content, which was set to 10.
The memory being pointed to has been released back to the system. That means that it will hold whatever value it had until the system assigns that block of memory to another variable and it gets overridden with a value.
Local variables are released when they go out of scope. If you are trying to return a value using an out parameter to a function:
void doSomething(int** num)
{
int* a = new int;
*a = 10;
*num = a;
}
int main()
{
int* number = 0;
doSomething(&number);
std::cout << *number << std::endl; // print 10 ???
if (number) delete number;
}
Though, for something this simple, you are better off just doing this:
int doSomething()
{
return 10;
}
int main()
{
std::cout << doSomething() << std::endl;
}