#include"iostream"
using namespace std;
class xxx
{
public:
char **a;
xxx();
~xxx();
};
xxx :: xxx()
{
a=new char*;
*a="10";
cout<<endl<<*a; // works fine
cout<<"Enter name:";
cin>>*a; // segmentation fault??
}
xxx :: ~xxx()
{
delete a;
}
main()
{
xxx x;
cout<<*x.a;
}
why can't I change the name field using cin ?
When i am calling a constructor it is assigning the value to the variable but While editing it is showing the following error:
program has stopped working.
same problem arises for method.What am I missing.
Within the constructor of xxx, *a is initialised so it points at (the first character of) a string literal.
The statement cin >> *a then attempts to modify the string literal. That gives undefined behaviour. The symptom you are describing is one possible outcome of undefined behaviour.
A simpler example, without the obfuscating details of class xxx would be
#include <iostream>
int main()
{
char **a = new char *;
*a = "10";
std::cout << std::endl << *a; // works fine
std::cout << "Enter name:";
std::cin >> *a; // undefined behaviour here
}
Although, as with any form of undefined behaviour, a particular outcome/symptom is not guaranteed.
You might try turning up warning levels for your compiler, and the result will probably be warnings about a suspicious conversion in the statement *a = "10" (e.g. converting something const to not const). Most modern C++ compilers (and quite a few older ones) are configured to NOT warn about such things by default, but can be configured to issue such warnings. Turning up compiler warnings, and taking heed of them, is helpful in reducing such types of undefined behaviour.
The problem with your code is quite simple, for that matter. In your constructor:
xxx :: xxx()
{
a=new char*;
*a="10";
cout<<endl<<*a; // works fine
cout<<"Enter name:";
cin>>*a; // segmentation fault??
}
You are trying to read into an already initialized string literal, which is then causing Undefined Behavior. If you want to do something like this, and you are using C++, you should probably switch to std::string, which will make your code a lot simpler without dealing with raw string literals and pointers, as follows:
#include <iostream>
#include <string>
class xxx
{
public:
std::string a;
xxx();
~xxx();
};
xxx :: xxx()
{
a = "10";
std::cout << std::endl << a;
std::cout << "Enter name:";
std::cin >> a;
}
int main()
{
xxx x;
std::cout<< x.a;
}
In this example, code such as a=new char*; and delete a; are removed along with the destructor itself. Other changes I made include changing your code to not using using namespace std; (Read why it is considered bad practice) and using the return type of int for main(). Additionally, I included the <string> library as well for std::string. Finally, as another recommendation, since std::cin will only read the first word passed to it and ignore the rest, if you want to read a full name then you can use getline() as follows:
//std::cin >> a; becomes...
getline(std::cin, a);
Issue in your code can be minimized to this snippet of invalid code:
char *p = "foobar"; // should not compile, but would on many compilers due to backward compatibility
p[0] = 'F';
issue is you are trying to modify memory where string literal resides which is UB.
Related
I am trying to program my own hangman game without refrencing other programs as a way to get back into programming.
Right now I am trying to program a structure that will hold all of the letters that will be alphabetized and displayed for the user. In the middle of trying to realloc i got this error
34 67 C:\Users\hanna\Documents\C Codes\Testing Hangman.cpp [Error] invalid conversion from 'void*' to 'Guess*' [-fpermissive]
Here is the code I am working with right now:
#include <ctime>
#include <stdio.h>
#include <iostream>
#include<stdlib.h>
#include <cstdlib> //has rand function
using std::cout;
using std::cin;
struct Guess {
char Letter[1];
};
int count = 0;
struct Guess*guessKeeper;
int main()
{
char choice;
cout << "Do you want to add another guess? \n";
cin >> choice;
cout << choice << "\n";
if (choice == 'y')
{
struct Guess newGuess;
cout << "What is your guess? \n";
cin >> newGuess.Letter;
guessKeeper = realloc(guessKeeper,(count+1)*sizeof(struct Guess));
count++;
guessKeeper[count-1] = newGuess;
cout << "Do you want to add another guess? \n";
cin >> choice;
};
free(guessKeeper); //Free Memory
}
Any recomendations on how to alphabetize would also be appretiated.
I have tried refrencing other online tutorials and some of my old code from my college classes; it is why I landed on structures as I have an old assignment that had used a structure and has code for alphabetizing I was hoping to refrence.
In C++ opposite to C you may not assign a pointer of the type void * to a pointer to an object type. You need to cast the return value of calls of for example realloc or malloc to the destination pointer type.
For example
guessKeeper = static_cast<Guess *>( realloc(guessKeeper,(count+1)*sizeof(struct Guess)) );
And in C++ you should use operators new and delete instead of realloc and free,
Also these statements in the end of the if statement
cout << "Do you want to add another guess? \n";
cin >> choice;
does not make sense because there is no loop in the program.
And this semicolon that defines a null-statement
//...
};
is redundant. Remove it.
And leave only the second include among these two includes
#include<stdlib.h>
#include <cstdlib> //has rand function
And remove this include
#include <stdio.h>
Also as correctly pointed #Blindy this declaration of the data member of an array type with one element does not make sense
struct Guess {
char Letter[1];
};
because this statement
cin >> newGuess.Letter;
results in memory corruption. That is it will try to read a string instead of a single character.
Instead you could declare the structure like for example
struct Guess {
char Letter;
};
I've just learned what a constant is in C++ and tried the following code on Code::Blocks and it gives me the following compile-time errors:
error: uninitialized constant 'b'[-fpermisive]
and
no match for operator >>
(I am using namespace std).
My guess is that uninitialised constants are not allowed in C++. Why is this so?
Note: I am learning to code for the first so, I will be glad if you can explain it without referring any other language.
const int b;
cin >> b;
Constants have to be initialised when they are declared, after they have been declared they cannot be changed.
If you want to store your value that you are reading from the console in a const the simplest way is probably to do so via a function:
int readInt()
{
int i;
std::cin >> i;
return i;
}
int main()
{
const int b = readInt();
}
#include <iostream>
#include <fstream>
using namespace std;
ifstream fin("BAC.TXT");
void eval(int a, int b, int &rez)
{
rez = a + b;
}
int main()
{
int nr;
int s;
fin >> s;
while (fin >> nr)
eval(s, nr, s);
cout << s << '\n';
return 0;
}
So I have this code snippet. I am reading numbers from a file and keeping track of their sum using a given function called “eval”. I know it could be considered bad code to pass a parameter twice (in such a given instance) rather than using another variable (not sure, though, if it is bad code or not, in my case). My problem is: will it change the value of variable s? Again, I am passing it once by value and once by reference! I have written the code on my PC and it does change the value of s. Now my question would be: why? If I am asking this in a right way: what happens “in the background”?
The fact that a is a copy of s is actually a red herring. Maybe that caused your confusion, but its just a copy. Consider that you could call the function like this
auto temp = s;
eval(temp,nr,s);
to get the exact same result. Inside the function rez is a reference to s, hence modifications on it will be reflected on s in main. In other words, rez is an alias for s, while a has no relation whatsoever to s, they just happen to hold the same value.
This question is related to the behavior of functions parameters and reference/pointers.
When you pass a value to a function, it copies the value you give to a local variable inside the function.
in your case, when you pass 's', it copies it to 'a' like if you would do it in your main: int a = s (this is what is going on)
The same applies to the reference. when you pass 's' to the third parameter, it does this:
int &rez = s
When you pass it by reference, it is sort of taking the address of the variable instead of the value itself and copying this address to a local variable that is already dereferenced. (pointer stuff)
So the value is changed.
See the video related to pointers and then reference on 'the Cherno Project' youtube channel for better comprehension of the subject:
Pointers
References
Short answer: Yes, s will be changed.
Long answer: Let me rewrite your code snippet a little bit to illustrate what is happening with the function parameters during a call:
#include <iostream>
#include <fstream>
using namespace std;
ifstream fin("BAC.TXT");
void eval(int a, int b, int &rez)
{
rez = a + b;
}
int main()
{
int nr;
int s;
fin >> s;
while(fin >> nr) {
int a = s;
int b = nr;
s = a + b;
}
cout << s << '\n';
return 0;
}
So, basically, a and b are just copies of s and nr respectively. However, res is s.
IMO, this is what I would expect :
Copy s to a new var l_S.
Copy nr to a new var l_Nr.
Copy &s to new var l_Ptr.
Add l_Nr and l_S.
Save the result in *l_Ptr.
I have got class "student.cpp"
#include <iostream>
#include "student.h"
using namespace std;
void student::setMarks(int m1, int m2) {
mark1 = m1;
mark2 = m2;
};
void student::setName(char *n) {
name = n;
};
int student::calc_media(void){
return (mark1+mark2)/2;
};
void student::disp(void){
cout << "Student:" << name << " \n media:"<< calc_media() <<"\n";
};
student::student(){
mark1 = 0;
mark2 =0;
name = "";
};
Header file "student.h":
ifndef CLASY_STUDENT_H
#define CLASY_STUDENT_H
#endif //CLASY_STUDENT_H
class student{
char *name;
int mark1, mark2;
public:
void setName(char *n);
void setMarks(int m1, int m2);
void disp(void);
int calc_media(void);
student();
};
And "main.cpp":
#include <iostream>
#include "student.h"
using namespace std;
int main() {
student s;
char* n;
int m1, m2;
cout << "Enter name:";
cin>> n;
cout << "Enter marks of two subjects:";
cin>> m1;
cin>> m2;
s.setName(n);
s.setMarks(m1, m2);
s.disp();
return 0;
}
I am running this usign Clion and Cmake is :
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
set(SOURCE_FILES main.cpp student.cpp student.h student.cpp student.h)
But when I run, it asks for name, but when I type something then I have got a memory fragmentation error. Whats wrong?
And could someone by the way tell me if it looks okey for C++? I am trying to switch from java to c++.
char* n;
...
cin>> n;
n is a pointer, supposed to point at a particular piece of memory. But you never set it. So it has some undefined value, pointing who-knows-where into some memory that you end up trying to overwrite. Most likely memory you are not allowed to overwrite, causing a segfault.
Don't try to use char* if you don't yet know about manual memory management (and once you do, you'll understand why not to). Use std::string.
From a quick glance, you can pretty much replace char* everywhere with std::string (as long as you #include <string>).
Similar to what others are saying, your variable n is an uninitialized pointer. Pointers, as the name suggests, are just signposts to a particular location in memory - the tell the CPU "go to this memory location for variable x".
Say you have an integer variable var, which is declared like this:
int var;
That variable occupies memory and you can assign it a value like this:
var = 5;
You can also declare a pointer to an integer like this:
int * var_ptr;
Now assuming var_ptr points to a valid integer I can assign a value to it like this:
*var_ptr = 5;
This says "put the number 5 at the memory location pointed to by var". However if var_ptr has not been initialized then it will point to a random location in memory that may overwrite something important, or attempt to write to a protected memory address causing a protection fault (segfault). This is what is happening in your code.
To initialize var_ptr to point to the address of var, we can do this:
var_ptr = &var;
The ampersand is the "address of" operator - it says "don't get me the value of var but instead get me the address of the memory location where var is stored".
So, to prevent your problem, you must initialize n to some valid memory location where you are able to safely write some data.
There are a few ways to do this. As #Stefan points out you can declare n to be a character array:
char n[20];
As #BobTFish points out you need some way to make sure that your input doesn't exceed the size of your array (20 bytes in this case). The solution is std::cin.width(20).
As #BobTFish also mentions, you could also using a std::string, like this:
std::string n;
std:cin >> n;
The std::string object will automatically take care of memory allocation.
If you really must use a char *, you can either take the address of a char array (here I take the address of the first element of the array):
char n_array[20];
char *n = &n_array[0];
std::cin.width(20);
std::cin >> n;
You could also use dynamic memory allocation:
char *n = new char[20];
std::cin.width(20);
std::cin >> n;
delete n;
Notice that if you use dynamic memory allocation you must free the memory using delete when you are done otherwise there will be a memory leak. Local variables (like the array) are allocated on the stack and therefore are automatically freed when the function returns. For this reason, and the overhead of dynamic memory allocation, you would be insane to use it here.
Was writing some code for an assignment to take integers as input and place them in an array to be printed.
I'm cleaning up all of my pointers as far as I can tell but I keep getting the runtime error:
1 [main] new 3444 cygwin_exception::open_stackdumpfile: Dumping stack trace to new.exe.stackdump
body of code:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int array[10];
int * p = array;
int *readNumbers()
{
int i=0;
for(i=0;i<10;i++)
{
string number;
int numb;
cout << "enter digit " << i << " of 10" << endl;
getline(cin, number);
istringstream (number) >> numb;
array[i]=numb;
}
return p;
delete p;
}
void printNumbers(int *numbers,int length)
{
int i;
for(i=0;i<length;i++)
{
cout << i << " " << *(numbers+i) << endl;
}
}
and the main calling code:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
extern int *readNumbers();
extern void printNumbers(int *,int);
int main()
{
int * q = readNumbers();
printNumbers(q,10);
delete q;
return 0;
}
So just looking for a solution to the stack dump...
Also I'm sure the method I used to apply the string number returned by cin to the values contained in array[10] is not what the question was looking for so any notes on that would be great.
Thanks
It is not a good practice to return a pointer to a memory allocated inside a function, in this case, you are not even allocating it inside a function, you have done it in a global space.
It is a good practice to activate all your warnings during the compile, even treat them as error when you are doing an assignment.
As a tip, you can allocate the memory in your main function and then pass the pointer to the readNumbers function.T This way it remains inside the same scope and it is easier to manage.
also, the same way you pass the lenght of the array to the printnumbers function you should pass it to the readnumbers one instead of hardcoding it.
Your delete are invalid, you can only delete something you've allocated with new.
The first one is harmless because it's after a return, so never executed (BTW you should look at compiler warnings).
The second one might produce your crash.
Also I'm sure the method I used to apply the string number returned by cin to the values contained in array[10] is not what the question was looking for so any notes on that would be great.
That's OK. What's dubious is spreading the size of the array everywhere, what happens if you want to change it ?