This is my code to receive string.
But I don't know what causes a problem.
Anybody knows?
#include<iostream>
#include<cstring>
using namespace std;
class person{
private:
char name[100];
//char * name;
public:
person(void) : name(){}
person(person& myPerson);
~person(void) {delete []name;}
void read();
void write();
};
person::person(person& myPerson ){
strcpy(name ,myPerson.name);
}
void person::read(){
cout<< "read name from console: " ;
cin >> name;
}
//////// <<---- problem point.
void person::write(){
cout << name << endl;
}
void main(void) {
person p1;
p1.read();
//p1.write();
getchar();
}
//I insert "getchar()" to remain console window for a while
Remove delete []name; from the destructor of person. You should only free memory that is heap allocated, with malloc() or new, and not space that is stack allocated, like your fixed-size array declared char name[100]. This change will fix the memory error you receive when the destructor is executed as the program exits.
Your code has a number of errors or bad style.
First, it's recommend to use C++ standard library facilities as much as possible. So use std::string instead of char[SIZE].
Second, use int main{return 0;} instead of void main{}.
Third, delete [] name; will lead to a memory error. You are freeing stack memory not heap memory.
Last, in my opinion, class names should start with a capital letter (Person).
Related
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 6 years ago.
#include <iostream>
#include<string.h>
using namespace std;
char *rt()
{
char a[20];
strcpy(a,"I am a beginner");
cout<<a;
return a;
}
int main()
{
char *a;
a=rt();
cout<<endl;
cout<<a;
return 0;
}
Here I have made a short program for understanding the same....I was expecting the output to be as
I am a beginner
I am a beginner
UPDATE:
But it turned out to be
I am a beginner
ëóG
I have read many articles and post but I am not able to understand their complex language....so I will appreciate a no-nonsense answer ( for a stupid...like me!!)
UPDATE:
Actually, there is one question in my assignment which goes like this
class COMPUTER
{
char chiptype[10];
int speed;
public:
void showdetails()
{
cout<<chiptype;
cout<<"\t"<<speed;
}
void getdetails()
{
cin.getline(chiptype,10);
cin>>speed;
}
};
Here the data has to be read and stored into a binary file....and the records having chiptype as "CD" are to be displayed.
Now my question is that...as the variable chiptype is private so I can't use it for comparison in main()....so I thought of making a function which returned the value stored in chiptype.
And I am not allowed to use std::string as well as node implementation...
char a[20]; is allocated on stack. When the function rt() returns, the stack unwinds and a goes out of scope. Hence you do not get your desired result.
While you are on C++, may I suggest using std::string
Read the comment below:
The other trick is to wrap the array in a struct, and return the
struct. Since a struct is copyable, the array internally becomes
copyable and will not lose scope. See this answer. Then you're not
dealing with pointers at all. See this live example – PaulMcKenzie
Use std::string instead of char[]
#include <iostream>
#include<string>
std::string rt()
{
std::string a("I am a beginner");
std::cout<<a;
return a;
}
int main()
{
std::string a;
a=rt();
std::cout<<std::endl;
std::cout<<a;
return 0;
}
In your original code char a[20] is allocated on the stack and return a; will return a pointer to a stack variable that is no longer valid when you receive it in you main() -- handling strings in c++ should generally be done using std::string as it handles all the nasty memory management that wil kill your program if you aren't careful.
If you have to use pointers and not use std::string, you would need to go the c style way with the risk of having memory leaks if you miss a step or two. The code would look something like this using c style (keeping the cout c++)
#include <iostream>
#include <strings.h>
std::string rt()
{
char *a = malloc(20); // allocate the memory on heap
strcpy(a,"I am a beginner");
std::cout<<a;
return a;
}
int main()
{
char *a;
a=rt();
std::cout<<std::endl;
std::cout<<a;
free(a); // release the memory
return 0;
}
Caution: I don't recommend that you do the above style -- in a real world application you will likely get into trouble by either forgetting to free the memory, or accidentally accessing the memory after it has been free'd
The problem is that the memory of a will be destroyed as soon as program returns from the function. I do not think you should work with dynamic memory at your level of knowledge, so I suggest you define the array outside and just modify it inside the function:
#include <iostream>
#include<string.h>
#define MAX_LENGTH 20
using namespace std;
void rt(char *a)
{
strcpy(a,"I am a beginner");
cout<<a;
}
int main()
{
char a[MAX_LENGTH];
rt(a);
cout<<endl;
cout<<a;
return 0;
}
Furthermore, you should take care that rt is not writing more than MAX_LENGTH characters.
As mentioned by other use std::string instead of char [].
std::string rt()
{
std:: string a = "I am a beginner"; // This statement is equivalent to std::string a("I am a beginner");
std::cout << a "\n";
return a;
}
Main reason of not getting the desired result is " char a[] is allocated on stack, but when function return stack become empty.
P.S : You need to include <string> in your program, to use std::string
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
class telephone
{
string name;
long number;
public :
void getdata();
void display();
};
void telephone :: getdata()
{
cout<<"Enter the name : ";
getline(cin,name);
cout<<"Enter the number : ";
cin>>number;
}
void telephone :: display()
{
cout<<"1. Name : "<<name<<endl;
cout<<"2. Number : "<<number<<endl;
}
int main()
{
fstream f;
telephone p,q;
f.open("dir.txt",ios::out);
p.getdata();
f.write((char*)&p,sizeof(telephone));
f.close();
f.open("dir.txt",ios::in);
while( f.read((char*)&q,sizeof(telephone)))
{
q.display();
}
f.close();
return 0;
}
I have written this code to write and read data from file in class object.It displays the output but shows some error.
OUTPUT :
Enter the name : rahul
Enter the number : 234546
1. Name : rahul
2. Number : 234546
*** Error in `./a.out': double free or corruption (fasttop): 0x08f861a8 ***
Aborted (core dumped)
I have tried by using file extension like .txt,.bin,.dat but it showed the same error.Please help me to remove this error.
Writing a telephone to a file as a binary blob will not work. telephone contains name and name is a std::string. A std::string does not typically contain the string data it represents; it contains a pointer to the string data.
So when you
f.write((char*)&p,sizeof(telephone));
what you actually wrote to the file was not the string data, but a pointer to the string data. This means that
f.read((char*)&q,sizeof(telephone));
reads back p's pointer to q and that means that p and q both point at the same string data. This is bad.
When p or q go out of scope and are destroyed, they destroy name, and name, like a good little std::string, and frees the memory it points at. This leaves the other object containing a std::string pointing at memory that has been freed, and sooner or later that other object will either be used and invoke undefined behaviour or be destroyed and attempt to free the previously freed memory. This is what is meant in the error message by "double free". The same memory has been freed twice.
In your case, if q is deleted before p, q releases the memory that both p and q point at leaving p pointing at an invalid memory location. A few nanoseconds later p is deleted and p cannot free the already freed memory.
To get around this you must ensure the contents of the std::string are written to the file and then read back. This is called serialization.
Typical solutions to this problem are to write the data to the file in a text format with << and read it back with >> (which may require you to implement the << and >> operators for your class)
class telephone
{
string name;
long number;
public :
void getdata();
void display();
friend std::istream & operator<<(std::istream & out, const telephone & tp);
friend std::ostream & operator>>(std::ostream & in, telephone & tp);
};
or add serialization functions to the class
class telephone
{
string name;
long number;
public :
void getdata();
void display();
bool serialize(std::iostream & out);
bool deserialize(std::iostream & in);
};
The writing of these functions is probably the point of this assignment, so I'll stop here. Don't worry. Both are approaches are exceedingly well documented online if you have trouble. I recommend starting with the first option. It is much easier to debug because you can read the text file to see if you got it wrong.
Note: While I was debugging, I found that until the last line, the program run normally, but when going by the last bracket, a mistake window would pop up. I'm not quite familiar with C++ so I couldn't locate the problem. Please help!
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
class test {
public:
int x;
void add_list(int);
void display();
private:
vector<int> list;
};
void test::add_list(int op)
{
list.push_back(op);
}
void test::display()
{
cout << x << endl;
for (unsigned int i=0;i<list.size(); i++)
cout << "->" << list[i];
cout << endl;
}
int main (void)
{
test test1;
test1.x = 3;
test1.add_list(2);
test1.add_list(4);
int size = sizeof (test1);
ofstream fout ("data.dat", ios_base::binary);
fout.write((char *)&test1, size);
fout.close();
ifstream fin ("data.dat", ios_base::binary);
test test2;
fin.read((char *)&test2, size);
test2.display();
fin.close();
return 0;
}
These lines
fout.write((char *)&test1, size);
and
fin.read((char *)&test2, size);
won't work because the test class contains objects that contain pointers. std::list will allocated extra memory using new to store items that are pushed on to it. It will then keep pointers to those items. When you write the object to disk, it will still contain those pointers to memory. When you load the object back again, the pointers will contain the same value, but your program may not have the same memory allocated and certainly won't have it allocated for the object.
In your case test2 appears to work because its internal pointers end up being the same as test1, however when you program finishes, the test1 destructor releases the memory that it allocated, then the test2 destructor tries to release the same memory, leading to your error.
To fix it, you should change your code to write the object in a defined format that doesn't use pointers (e.g. write out the item count followed by each items integer value). Then read them in the same way. One simple fwrite won't be able to do it.
I have basic file handling code of reading file named"student.dat" using visual studio.
the output reads the file and displays the result in console but visual studio pops up the dialog as
code:
#include<iostream>
#include<fstream>
#include<conio.h>
#include<string>
using namespace std;
class student
{
int admno;
// char name[20];
string name;
public:
void getdata()
{
cout<<"\n\nEnter The Name of The Student ";
//gets(name);
cin>>name;
getch();
cout<<"\nEnter The admission no. ";
cin>>admno;
// getch();
}
void showdata()
{
cout<<"\nAdmission no. : "<<admno;
cout<<"\nStudent Name : ";
cout<<name;
//puts(name);
}
int retadmno()
{
return admno;
}
};
int main()
{
student obj;
ifstream fp1;
fp1.open("student.dat",ios::binary);
while(fp1.read((char*)&obj,sizeof(obj)))
{
obj.showdata();
}
fp1.close();
return 0;
}
You are allowed to load raw data only to some POD objects. This line is an error:
fp1.read( (char*)&obj,sizeof(obj) );
because student contains std::string. std::string contains a pointer to a memory block which becomes invalid and totally useless after the object is destroyed. It means the data you load to std::string is just a garbage.
I'd think about object serialization. Boost serialization is a good way to start.
You try to store/load an object to a file, which is invalid.
while(fp1.read((char*)&obj,sizeof(obj)))
Objects may contain references to memory (std::string e.g.) that are invalid after loading. You have to provide serialization for your objects or use plain structs without pointers or references to store your data. E.g.:
struct {
int admno;
char[20] name;
}
If you need strings with variable length, you may use a string store:
struct {
int admno;
size_t name_index;
}
std::vector<std::string> names;
To store, iterate over your names and save length and .c_str of each std::string. To read, do it the other way around and read length into n, read n bytes into a buffer and construct a std::string out of the buffer.
You might have a look at http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/index.html
You never call GetData so admno is not instantiated in ShowData
There may be other examples, but this is the one I just came across.
#include <iostream>
using namespace std;
class Student
{
public:
int x;
};
int main()
{
Student rts;
Student* heap = new Student;
cout << rts.x << endl; // prints out random integer
cout << heap->x << endl; // prints out 0
}
Is there any good reason or logic to understand behind this?
In this instance I think it is just coincidence that the heap is already zeroed in the memory that is allocated.
You can read more in the answers to this similar question
Always initialize your variable to something meaningful. Else its allowed to take any values at random.
class Student {
public:
int x;
Student(): x(0) {}
};