#include <iostream>
#include <fstream>
#include <cmath>
#include <string>
#include <sstream>
using namespace std;
class CFile {
public:
CFile(string filename);
~CFile();
void ReadFile();
void WriteFile(string outputFilename);
void Calculate();
string m_filename;
int m_numberInput;
double* m_xData;
double* m_yData;
int m_numberOutput;
double* m_xDataOut;
double* m_yDataOut;
};
CFile::CFile(string filename)
{
m_filename = filename;
string line;
ifstream myfile(m_filename.c_str());
if (myfile.is_open())
{
getline(myfile,line);
myfile.close();
stringstream Str;
Str << line;
Str >> m_numberInput;
m_xData = new double[m_numberInput];
m_yData = new double[m_numberInput];
cout << sizeof(m_xData) / sizeof(m_xData[0]) << endl;
}
else cout << "Unable to open file.\n";
}
CFile::~CFile()
{
delete[] m_xData;
delete[] m_yData;
m_xData = 0;
m_yData = 0;
delete[] m_xDataOut;
delete[] m_yDataOut;
m_xDataOut = 0;
m_yDataOut = 0;
}
void CFile::ReadFile()
{
ifstream infile(m_filename.c_str());
string line;
if (infile.is_open())
{
int x, y, i = 0;
while (getline(infile,line))
{
infile >> x >> y;
m_xData[i] = x;
m_yData[i] = y;
i++;
}
infile.close();
}
else cout << "Unable to open file.\n";
}
void CFile::WriteFile(string outputFilename)
{
ofstream outfile(outputFilename.c_str());
if (outfile.is_open())
{
for(int i=0; i < m_numberInput; i++)
outfile << m_xDataOut[i] << " " << m_yDataOut[i] << endl;
outfile.close();
}
else cout << "Unable to open file.\n";
}
void CFile::Calculate()
{
m_xDataOut = new double[m_numberInput];
m_yDataOut = new double[m_numberInput];
for(int i=0; i < m_numberInput; i++)
{
m_xDataOut[i] = m_xData[i];
m_yDataOut[i] = sqrt(m_yData[i]);
}
}
int main()
{
CFile file("Input.dat");
file.ReadFile();
file.Calculate();
file.WriteFile("Output.dat");
file.~CFile();
}
The error message is as follows:
main(11915,0x7fff77d3d310) malloc: *** error for object 0x7f8a99403940: pointer
being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
This is code which ironically worked well some weeks ago. I change OS and compilers and now it doesn't anymore. I read about this error in other threads, but couldn't really understand how to use the solutions on my code. The code reads in a data file, does sth. with it and then writes the changed values into another file.
Where is the allocation error?
Thank you very much in advance for your help! :-)
Your Destructor is called twice. You call it explicitly, and it is also called when exiting main(). You should remove your explicit destrcutor call.
Two problems:
You don't necessarily initialise all four pointers, in which case it's not safe to apply delete to them. You can fix this by initialising them to null before doing anything; or, better still, replace them with std::vector<double> so you don't have to mess around with delete at all. That will also fix the class's invalid copy semantics (it breaks the Rule of Three) and the potential memory leaks if construction fails.
You're calling the destructor manually (file.~CFile(), at the end of main). Don't do that: the destructor is called automatically when the program leaves the variable's scope, and it's an error to call it twice.
As #claptrap pointed out your memory managements were also buggy.
You should migrate to std::vector<double> rather than raw double arrays and pointers. You can think of vec.resize(N) as a variant of new double[N] which never needs an explicit delete[].
If you are on Linux, it's a good practice to run your program under valgrind which automatically traces memomry allocations/deallocations and points out any invalid memory operations. I bet your Linux distro has a pre-compiled package for it.
http://valgrind.org/docs/manual/quick-start.html
This here is causing the issue
delete[] m_xDataOut;
delete[] m_yDataOut;
you have not initialized the pointers in your constructor
Related
I am currently trying to learn C++. I am given a .txt file that contains a different individuals data on each line. I want to read that data into an array of strings. I don't see anything wrong with this function and I have done the same thing before, but for some reason I am receiving a segmentation fault.
#include <string>
#include <iostream>
#include <fstream>
void readFile(std::istream&, std::string*);
int lineCount(std::istream&);
int main(){
std::ifstream inFile("input.txt");
int numLines = lineCount(inFile);
std::string data[numLines];
inFile.close();
inFile.open("input.txt");
readFile(inFile, data);
inFile.close();
return 0;
}
int lineCount(std::istream& inFile){
std::string line;
int numLines = 0;
while(std::getline(inFile, line)){
numLines++;
}
return numLines;
}
void readFile(std::istream& inFile, std::string *data){
int i = 0;
while(std::getline(inFile, data[i])){
std::cout << i << "\n"; //testing values
std::cout << data[i] << "\n"; //testing values
i++;
}
}
Here is the output of the above code.
//Output
//Note, these are fictional people
0
Florence,Forrest,1843 Glenview Drive,,Corpus Christi,TX,78401,10/12/1992,5/14/2012,3.215,127/11/1234,2.5,50
1
Casey,Roberta,3668 Thunder Road,,Palo Alto,CA,94306,2/13/1983,5/14/2014,2.978,95
2
Koch,Sandra,2707 Waterview Lane,Apt 302,Las Vegas,NM,87701,6/6/1972,12/14/2015,2.546,69
Segmentation fault //occurs in while condition
Any help would be appreciated
I feel sick that I didn't see this right away.
int numLines = lineCount(inFile);
returns the correct number of lines in the file. Bug's not here, man.
std::string data[numLines];
Is not kosher C++, but will create an array with an element for every line in the file if supported. Your program is running, so it's supported. Still, prefer to use Library Containers.
Meanwhile in readFile...
while(std::getline(inFile, data[i]))
Will try to read a line into data[i]. Whether the read succeeds or not, there must be a data[i] to read into. There won't be for the last try.
The logic goes
read in line 1. Successful, so
read in line 2. Successful, so
read in line 3. Successful, so
read in line 4. Fail. But this does not keep getline from looking off the end of data for a string and going boom (specifically undefined behaviour that manifested as going boom) because there isn't one.
The right solution
int main(){
std::ifstream inFile("input.txt");
// no longer need. Vector keeps track for us
// int numLines = lineCount(inFile);
std::vector<std::string> data;
// read nothing from file. Don't need to rewind
readFile(inFile, data);
// note: files close themselves when they are destroyed.
//inFile.close();
return 0;
}
void readFile(std::istream& inFile, std::vector<std::string> & data){
int i = 0;
std::string line; // line to read into. Always there, so we don't have to worry.
while(std::getline(inFile, line)){
std::cout << i << "\n"; //testing values
std::cout << line << "\n"; //testing values
data.push_back(line); // stuff line into vector.
i++;
}
}
The No vector Allowed Solution
int main(){
std::ifstream inFile("input.txt");
int numLines = lineCount(inFile);
// legal in every C++, but prefer container may want some extra armour
// here to protect from numlines 0.
std::string * data = new std::string[numlines];
// the following is a faster way to rewind a file than closing and re-opening
inFile.clear(); // clear the EOF flag
inFile.seekg(0, ios::beg); // rewind file.
readFile(inFile, data);
inFile.close();
return 0;
}
void readFile(std::istream& inFile, std::string * data){
int i = 0;
std::string line; // same as above. line is here even if data[i] isn't
while(std::getline(inFile, line)){
std::cout << i << "\n"; //testing values
std::cout << line << "\n"; //testing values
data[i] = line; // stuff line into array. Smart compiler may realize it can move
//if not, c++11 adds a formal std::move to force it.
i++;
}
}
I'm trying to serialize and deserialize an object which contains a vector
using ofstream and ifstream. The process of serialization works like a charm, but as soon as I call the read method of ifstream, I get a double free or corruption exception. This is my code:
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
class A
{
private:
vector<int> v;
public:
void add(int e) {
v.push_back(e);
}
void print() {
vector<int>::iterator it;
cout << "[" << v.at(0);
for(it = v.begin()+1; it!=v.end(); ++it)
cout << "," << *it;
cout << "]" << endl;
}
};
int main()
{
A a;
A s;
ofstream ofs;
ifstream ifs;
for (int i=1; i<= 10; i++)
a.add(i);
a.print();
ofs.open("s.bin", ios::binary);
ofs.write((char *) &a, sizeof(a));
ofs.close();
ifs.open("s.bin", ios::binary);
ifs.read((char *) &s, sizeof(s));
ifs.close();
cout << "s: ";
s.print();
return 0;
}
A strange behavior is, that the program prints out the deserialized object. This is my outout:
[1,2,3,4,5,6,7,8,9,10]
s: [1,2,3,4,5,6,7,8,9,10]
*** Error in `./a.out': double free or corruption (fasttop): 0x000000000187c080 ***
Any ideas what causes this problem? I'm clueless.
You have undefined behaviour, and it appears that in your particular case what's probably happening is that the pointers to a's dynamically allocated buffer - which stores the numbers - are written to disk then read back in over the memory for s, such that the s object believes itself the rightful owner of the same dynamic buffer as a.
As execution leaves the scope of main(), s's destructor runs and releases that buffer, then a's destructor tries to release the same buffer, hence "double free".
If you want to serialise elements properly, I recommend the boost::serialize library. Failing that, at least write a.size() * sizeof a[0] bytes from a.data(): the actual contained data and not the vector object managing that buffer. Afterwards, use resize on s to get it to allocate suitable memory and read the same number of bytes to s.data(). If you wanted to generalise the code to support varying numbers of elements you're write out the size first, and if you want portability you'd use hton/ntoh to handle endianness.
I am trying to use dynamic memory for this project. I am getting a seg fault but I cannot figure out what I am doing incorrectly. Can anyone point to where my mistake is? The file seems to read in correctly...but im assuming the fault is a rogue pointer..help!
I am just trying to read in "heart two 2" to "spade ace 11" in from a file, all words seperated by a space. my program worked before using dynamic memory..
#include <iostream>
#include <fstream>
#include <ctime>
#include <stdlib.h>
#include <string>
using namespace std;
//global constant(s)
const int maxCards = 52;
//Structs
struct card
{
char *suit;
char *rank;
int cvalue;
char location;
};
void readDeck(card* deckPtr);
void cardsInit(char *finNameP,card *deckPtr);
//program
int main()
{
card *deckPtr = new card[52];
char *finNameP = new char[13];
strcopy(finNameP,"cardFile.txt");
cardsInit(finNameP,deckPtr); // function i wrote that works
readDeck(deckPtr); //simply reads the deck from &deckPtr[0] -> &deck[51]
delete [] finNameP;
}
void cardsInit(char *finNameP, card *deckPtr)
{
//set up card file to be read in
ifstream fin;
cout << "Please enter file name...(cardFile.txt)" << endl;;
cin >> *finNameP;
fin.open(finNameP);
//create pointer and set initial value
card *deckHome = deckPtr;
for(int i=0;i<52;i++)
{
(*deckPtr).suit = new char[9];
(*deckPtr).rank = new char[9];
deckPtr++;
}
deckPtr = deckHome;
//check if cardFile.txt opens correctly
if(!fin.good())
{
cout << "Error with card file" << endl;
}
else
{
while(fin.good())
{
for(deckPtr = &deckPtr[0]; deckPtr < &deckPtr[maxCards];deckPtr++)
{
fin >> (*deckPtr).suit;
fin >> (*deckPtr).rank;
fin >> (*deckPtr).cvalue;
}
}
}
fin.close();
delete []finNameP;
delete [] (*deckPtr).suit;
delete [] (*deckPtr).rank;
}
This is a really ancient way to program. Instead of using new, use std::string or std::vector<char>. Those also use dynamic memory but they make it much harder for you to accidentally cause memory allocation bugs.
The first problem comes here:
cin >> *finNameP;
Since finNameP has type char *, then *finNameP has type char. So this instruction reads a single character. Then you go onto do fin.open(finNameP); which causes undefined behaviour because there is no string in finNameP.
The simplest fix is to make finNameP be a std::string. Note that doing cin >> finNameP (without changing the type) would compile, however it is a bad idea because there is no buffer overflow protection. You could write cin >> setw(12) >> finNameP; but that is still substantially worse than using a string.
deckPtr < &deckPtr[maxCards] is always true, the for loop runs forever.
working on some code that will place (output/input) 5 different files onto my desktop. Finally, got it down to one error message which is "error <23>: C2109: subscript an array or pointer type is required". Its with myfile.open; I've tried -> operator. Not exactly how to make this into an array, if that is what I'm suppose to do as I have tried making string into char and warnings occur. Can anybody let me know how I can modify my code to correct this? I'm relatively new to C++ and programming, only a few months.
#include <iostream>
#include <fstream>
using namespace std;
struct pizza{
string FILENAMES[9];
};
int main ()
{
int i;
char FILENAMES;
pizza greg = {"file1.doc", "file2.doc", "file3.doc", "file4.doc", "file5.doc"};
cout << "Input is invalid. Program will end. " << "\n" ;
for (i = 0; i < 5; i++)
{
const char *path="/Desktop/Libraries/Documents" ;
ofstream myfile(path);
myfile.open (FILENAMES[i]) ;
myfile << "How you like math?\n" ;
myfile.close();
};
return 0;
}
Your suggestions helped a lot, and my program is now up and running. (no pun intended, haha.)
The loop should really look something like this:
const char *path="/Desktop/Libraries/Documents";
for (int i = 0; i < 5; ++i)
{
std::string name(path + greg.FILENAMES[i]);
std::ofstream myfile(name.c_str());
if (myfile) {
myfile << "How you like math?\n" ;
}
else {
std::cerr << "ERROR: failed to open '" << name << "' for writing\n";
}
}
char FILENAMES;
FILENAMES is not an array. Even if it were, you would have to make it an array of strings or a two dimensional array of characters to do what you intend here.
What you probably intend to do is access the field inside greg.
myfile.open (greg.FILENAMES[i]);
I've narrowed my code down, and I found the source of the problem, it's when I open a file.
The file does exists, and I don't get any warning or errors when compiling.
int main(int argc, const char* args[])
{
cout << "Wellcome" << endl;
cout << args[1];
ifstream exists(args[1]);
if(!exists)
{
printf("FILE NOT FOUND");
return 1;
}
exists.close();
ifstream* in;
in->open(args[1],ios::binary|ios::in);
//do stuff
in->close();
return 0;
}
You have created a pointer to an ifstream object, but you never allocated an ifstream for it to point to. To fix this, consider just stack-allocating it:
ifstream in;
in.open(args[1],ios::binary|ios::in);
//do stuff
in.close();
In general, you usually don't need to dynamically allocate objects unless you want them to outlive the function that created them.
Hope this helps!