Getting heap corruption when writing to a file - c++

Im trying to write a powerset to a file, but I get a heap corruption if my starting array is bigger than size 6, and im not sure why. It works fine with any size of array 6 or under. Cant figure this out.
Also, test.txt is where I read in the array. If the file contains"1,2,3,4,5,6" it works fine, but it it contains "1,2,3,4,5,6,7" I get heap corruption.
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include "N26.h"
#include <math.h>
using namespace std;
void increaseArray(int* theArray, int size)
{
int i = size;
int n = i+1;
int* newArray = new int[n];
for(int cnt=0;cnt<n;cnt++)
{
newArray[cnt] = theArray[cnt];
}
newArray[n-1]= NULL;
theArray = newArray;
return;
}
void printPowerSet(int *s, int n)
{
int i=0,j=0;
ofstream myFile;
double SetSize=pow(2.0,n);
myFile.open("powerset1.txt", std::ios_base::app);
cout<<"{size of original}"<< n <<endl;
cout<<"{number of sets}"<< SetSize-1 <<endl;
for(i=1;i<SetSize;++i)
{
for(j=0;j<n;++j)
{
if(((i>>j)&1)==1)
{
myFile << s[j] <<",";
}
}
myFile<<endl;
}
return;
}
int main()
{
ifstream myFile;
int item;
string input ="";
string fileName = "test.txt";
myFile.open(fileName);
while(myFile)
{
int k = 1;
int* transaction= new int[1];
if(!getline(myFile,input))
break;
istringstream ss(input);
while(ss)
{
if(!getline(ss,input, ','))
break;
input.erase(remove_if(input.begin(), input.end(), isspace), input.end());
item = atoi(input.c_str());
transaction[k-1] = item;
increaseArray(transaction,k);
k++;
}
for(int i =0; i<k-1;i++)
{
cout << transaction[i];
}
printPowerSet(transaction, k-1);
cout << endl;
transaction=NULL;
}
system("Pause");
return 0;
}

Your increaseArray() function doesn't work because you're only changing a local copy of the pointer. You'd have to pass a double pointer or a pointer reference to do what you want.
Example of a reference to pointer:
void increaseArray(int*& theArray, int size)
Instead, I'd recommend using a std::vector, since this will grow automatically.
I doubt this has any bearing on your problem, but I don't see that you ever delete, either. You are leaking memory. Before reassigning your pointer with a new allocation, delete the old allocation:
delete [] theArray; // The "[]" is important!
theArray = newArray;

In addition to Fred's answer.
Look at what's going on inside increaseArray(), specifically these lines:
int i = size;
int n = i+1;
int* newArray = new int[n];
for(int cnt=0;cnt<n;cnt++)
{
newArray[cnt] = theArray[cnt];
}
You allocate an array of size + 1 elements, and then iterate over the original. That's off-by-one, i.e. you are accessing one element outside of the original array. That might get you a segmentation fault depending on how new lays out the heap, but sure is undefined behavior.

Related

Dynamic array of char* (or 2d dynamic array of chars)

I'm getting funky output when running this code. There isn't a compile error. As far as I can tell, the problem is in my getArgs(stringstream& ss, int size) function. The strings are not copying correctly into my char* variables. I wanted a dynamic array of char* to save my command line arguments to. What am I doing wrong here?
#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct arguments
{
int argc; //number of arguments
char **argv; //array of arguments
};
void startupMsg()
{
cout << "******** CS415 SHELL ********" << endl;
}
int countArgs(stringstream& ss)
{
string temp;
int count = 0;
while (ss >> temp)
{
count++;
}
return count;
}
char** getArgs(stringstream& ss, int size)
{
ss.clear();
ss.seekg(0, ios::beg);
char **ary = new char*[size];
for (int i = 0; i < size; i++)
ary[i] = new char;
int c = 0;
string temp;
while (ss >> temp)
{
ary[c] = const_cast<char*>(temp.c_str());
c++;
}
return ary;
}
void printArgs(arguments* args)
{
for (int i = 0; i < args->argc; i++)
{
cout << args->argv[i] << " ";
}
cout << endl;
}
arguments* parseCommand(string command)
{
arguments *args = new arguments;
stringstream ss(command);
args->argc = countArgs(ss);
args->argv = getArgs(ss, args->argc);
return args;
}
int main()
{
string command;
startupMsg();
//while(true)
//{
cout << "user#linux:~$ ";
getline(cin, command);
arguments *args = parseCommand(command);
cout << args->argc << endl;
printArgs(args);
//}
}
Your problem is here:
ary[c] = const_cast<char*>(temp.c_str());
A good rule of thumb is when you find yourself needing const_cast, you're probably doing something wrong. It's not like you never need it, but it's quite an exceptional thing.
In any case, what happens here? Okay, you read into ary[0] a pointer into temp's buffer. Now you get your next argument. Best case, ary[0] and ary[1] now point to the same argument and you've lost the first one. Worst case, temp had to reallocate and now ary[0] is already a dangling pointer.
Regardless, at the end of getArgs(), temp is destroyed, and now all your likely-not-even-different pointers are dangling.
That's bad. You'll need to come up with some different.

Why do I see the contents of binary files?

Why I can open and view binary files . odd appearance that is impossible ?
http://codepad.org/OwX99H0p
Enter a string str -> char arr1[] -> FILEOUT.DAT
FILEOUT.DAT -> char arr2[] -> Printed screens
The code in question:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
void NhapMang(char *&arr, string str , int &n)
{
n = str.length();
arr = new char[n];
for (int i = 0; i < n;i++)
{
arr[i] = str[i];
}
}
void XuatMang(char *arr, int n)
{
for (int i = 0; i < n;i++)
{
cout << arr[i];
}
}
void GhiFile(ofstream &FileOut, char *arr, int n)
{
FileOut.open("OUTPUT.DAT", ios::out | ios::binary);
FileOut.write(arr, n*sizeof(char));
FileOut.close();
}
void DocFile(ifstream &FileInt, char *&arr, int n)
{
FileInt.open("OUTPUT.DAT", ios::in | ios::binary);
arr = new char[n];
FileInt.read(arr, n*sizeof(char));
FileInt.close();
}
int main()
{
char *arr1;
int n1;
fflush(stdin);
string str;
getline(cin, str);
NhapMang(arr1, str,n1);
ofstream FileOut;
GhiFile(FileOut, arr1, n1);
char *arr2;
int n2 = n1;
ifstream FileInt;
DocFile(FileInt, arr2, n2);
XuatMang(arr2, n2);
delete[] arr1;
delete[] arr2;
system("pause");
return 0;
}
You're ultimately storing data in a file. What this data represents is up to you, keep in mind, it's all '1's and '0's in the end. When you open the file you've created with a text editor, it will try to interpret this data as text which doesn't give a readable result.
Imagine storing a liquid in a bottle. If you don't label it, no one knows what it is. If you then pour this liquid in your car, it will try to use this as gasoline and potentially wreck your engine. Computers, fortunately, are much more forgiving.
Most files store information about how the data can be interpreted in their headers so programs can check if the file type is supported or not. So trying to open this file in a media player for example is most likely telling you that this format is not supported instead of trying to interpret the data as a media.

"Segmentation Fault [Core Dumped]" while initializing 2d array of char dynamically [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I want to get an array of strings from user. I am getting the exception "Segmentation Fault [Core Dumped]" on runtime.
#include <iostream>
#include <iomanip>
#include <math.h>
#include <string.h>
using namespace std;
int main() {
long testCaseCount = 0;
cin >> testCaseCount;
char **testCases;
*testCases = new char[testCaseCount];
for(int i=0;i<testCaseCount;i++) {
cin >> testCases[i];
}
}
You're not allocating space for each string being read. The following are two ways to do what you're trying, the first being the mostly-C approach you seem to want to take, the second fully exploiting the standard library for all its glory.
Both of the following examples should result in the same test strings given the same input content. The first resizes with each new additional char arrival. Though it may seem overkill, it is actually simpler than maintaining a geometric growth algorithm.
That said, here is the code. I leave it to you to decide which of these is more prone to errors and bugs (and I just wrote both online, so there are bound to be bugs regardless).
The Hard Way
#include <iostream>
#include <cstdlib>
#include <cctype>
using namespace std;
int main()
{
unsigned int testCaseCount = 0;
char **testCases = NULL;
// read and validate we received a count greater than zero
if (cin >> testCaseCount && testCaseCount > 0)
{
// allocate + nullinitialize that many pointers
testCases = new char *[testCaseCount]();
for (unsigned int i = 0; i < testCaseCount && cin; ++i)
{
// skip leading whitespace
char ch;
while (cin.get(ch) && std::isspace(ch));
if (cin)
{
// read chars until whitespace or EOF. vsize
// represents the size of the allocated buffer
char *value = new char[1]();
size_t vsize = 1;
while (cin.get(ch) && !std::isspace(ch))
{
// allocate larger buffer
char *tmp = new char[vsize + 1];
// copy in old content to new buffer
std::copy(value, value + vsize, tmp);
std::swap(value, tmp);
// save new char and terminator
value[vsize - 1] = ch;
value[vsize++] = 0;
// delete old buffer
delete[] tmp;
}
// save accumulated value.
testCases[i] = value;
}
}
}
// show test cases
for (unsigned int i = 0; i < testCaseCount && testCases[i]; ++i)
std::cout << testCases[i] << '\n';
// cleanup
for (unsigned int i = 0; i < testCaseCount && testCases[i]; ++i)
delete[] testCases[i];
delete[] testCases;
return 0;
}
The Easy Way
#include <iostream>
#include <iterator>
#include <vector>
#include <string>
int main()
{
unsigned int testCaseCount = 0;
std::vector<std::string> testCases;
if (cin >> testCaseCount)
{
std::string s;
while (testCaseCount-- && cin >> s)
testCases.emplace_back(s);
}
// show test cases
for (auto const& s : testCases)
std::cout << s << '\n';
return 0;
}
You have to write at least as
char **testCases = new char *;
*testCases = new char[testCaseCount];
Though it is not clear why you do not want to write simply as
char *testCases = new char[testCaseCount];
And do not forget to delete what was allocated with the operator new.
Take into account that it is not "an array of strings". It is simply an array of characters. If you want to get an array of strings you should at first decide what will be the maximum length of a string.
First you need to allocate space for the pointers to the first character of each string:
char** testCases = new char*[testCaseCount];
Then you'll need to allocate space for each string:
testCaseCount[i] = new char[maxStringLength];
cin >> testCaseCount[i];
However, this is dangerous-- cin won't do any bounds checking. You really should use std::string.
Getting Exception "Segmentation Fault [Core Dumped]" on runtime.
You have undefined behavior by dereferencing an undefined pointer in:
*testCases = new char[testCaseCount];
Objective: I want to get an array of strings from user
In c++ you use an std::string and an std::vector:
#include <iostream>
#include <string>
#include <vector>
int main() {
long testCaseCount = 0;
std::cin >> testCaseCount;
std::vector<std::string> testCases(testCaseCount);
for (auto& s : testCases)
std::cin >> s;
}
Live demo

Determining why C++ program chrashes

I'm doing a C++ project for a PCB assembly thesis and I have been given (by my professor) an old set of C++ code. When I try test and run the code it chrashes...the program compiles ok, but it chrashes at runtime..here is the code:
main.cpp:
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <ctime>
#include <climits>
#include "NozzleBank.h"
#include "PlacementHead.h"
int main (int argc, char * const argv[]) {
std::vector<char> list;
for (int i=0; i<3; i++) {list.push_back('a');}
for (int i=0; i<3; i++) {list.push_back('b');}
for (int i=0; i<3; i++) {list.push_back('c');}
for (int i=0; i<3; i++) {list.push_back('d');}
for (int i=0; i<3; i++) {list.push_back('_');}
int i = 0;
char set[list.size()];
while (!list.empty()) {
int x = (rand() % list.size());
set[i] = list.at(x);
list.erase(list.begin()+x);
i++;
}
NozzleBank bank(15,set);
PlacementHead head(4,2,1,"abababab");
return 0;
}
PlacementHead.cpp:
#include "PlacementHead.h"
#include <string>
#include <iostream>
#include <string.h>
PlacementHead::PlacementHead(int width, int height, int gap, char* s) {
width_ = width;
height_ = height;
gap_ = gap;
size_ = (width*height)+1;
set_ = new char[size_];
from_ = new int[size_];
original_ = new char[size_];
strcpy(set_,s);
strcpy(original_,s);
}
PlacementHead::~PlacementHead() {
}
int PlacementHead::getSize() { return size_; }
int PlacementHead::getHeight() { return height_; }
int PlacementHead::getWidth() { return width_; }
int PlacementHead::getGap() { return gap_; }
// Palauttaa indeksissä i olevan suuttimen
char PlacementHead::getNozzle(int i) {
return set_[i-1];
}
// Asettaa indeksissä i olevan suuttimen
void PlacementHead::setNozzle(int i, char c) {
set_[i-1] = c;
}
// Merkitsee suuttimen poimituksi poistamalla sen listasta
void PlacementHead::markNozzle(int i, int bankPos) {
set_[i-1] = ' ';
from_[i-1] = bankPos;
}
// Palauttaa seuraavan poimimattoman suuttimen indeksin
int PlacementHead::getNextUnmarkedPos() {
for (int i=0; i<size_; i++) {
if (set_[i]!=' ') {
return i+1;
}
}
return 0;
}
// Palauttaa suuttimen alkuperäisen sijainnin pankissa
int PlacementHead::getBankPos(int i) {
return from_[i-1];
}
// Plauttaa alkuperäisen ladontapaan suutinjärjestyksen
void PlacementHead::reset() {
//for (int i=0; i<size_; i++) {
// set_[i] = original_[i];
//}
strcpy(set_,original_);
}
// Tulostusmetodi
void PlacementHead::print() {
std::cout << "ladontapää:\n";
for (int h=height_; h>0; h--) {
for (int w=width_; w>0; w--) {
int i = ((h-1)*width_)+w;
std::cout << getNozzle(i);
}
std::cout << "\n";
}
}
NozzleBank.cpp:
#include "NozzleBank.h"
#include <string>
#include <iostream>
#include <string.h>
NozzleBank::NozzleBank(int size) {
bank_ = new char[size];
original_ = new char[size];
size_=size;
for (int i=0; i<size_; i++) {
bank_[i] = ' ';
original_[i] = ' ';
}
}
NozzleBank::NozzleBank(int size, char* s) {
bank_ = new char[size];
original_ = new char[size];
size_ = size;
strcpy(bank_,s);
strcpy(original_,s);
}
NozzleBank::~NozzleBank() {
}
int NozzleBank::getSize() { return size_; }
// Palauttaa pankin alkuperäisen järjestyksen
void NozzleBank::reset() {
strcpy(bank_,original_);
}
// Asettaa indeksissä i olevan suuttimen
void NozzleBank::setNozzle(int i, char c) {
bank_[i-1] = c;
original_[i-1] = c;
}
// Palauttaa indeksissä i olevan suuttimen
char NozzleBank::getNozzle(int i) {
return bank_[i-1];
}
// Poimii suuttimen poistamalla sen listasta
void NozzleBank::pickNozzle(int i) {
bank_[i-1] = ' ';
}
// Tulostusmetodi
void NozzleBank::print() {
for (int i=size_; i>0; i--) {
std::cout << bank_[i-1];
}
}
When I run the program I get the following:
Now here is also an interesting thing: IF I switch the order of the following lines in main.cpp
NozzleBank bank(15,set);
PlacementHead head(4,2,1,"abababab");
to:
PlacementHead head(4,2,1,"abababab");
NozzleBank bank(15,set);
The program runs fine...:O? And here I get like whaaaat...I'm a bit newbie in C++ so I'd appreciate if someone could see what's the problem :) Thank you for any help!
The C library strcpy() requires a NUL terminated C style string. You have a char[] array that does not have a NUL terminator.
If you want to convert your randomized array of letters into a C-style string, you need to add one more element to the end, and set it to the value 0. Alternately, you need to turn your strcpy() calls into memcpy() calls and supply the length directly.
In terms of minimal code changes, adding a NUL terminator requires the fewest changes to your code. Change this:
char set[list.size()];
to this:
char set[list.size() + 1];
set[list.size()] = 0;
And then change all of your new char[size_] calls to new char[size_ + 1].
The cleaner approach would be to say what you mean, and treat this as an array of char, not a C string. Convert all your strcpy calls to memcpy. For example, this:
strcpy(set_,s);
strcpy(original_,s);
becomes this:
memcpy(set_,s,size_);
memcpy(original_,s,size_);
Note: Be sure to change all strcpy to memcpy on these arrays. I think there is at least one other. I did not check your code that closely.
The latter is the better approach, IMHO, but I offer both.
Also, the above code leaks memory. That may not be a concern if it just runs through once and quits. You new [] memory that you never delete []. If your program is going to grow and have multiple instances of these objects coming and going, you'll want to add those delete[] calls, otherwise you're setting yourself up for a future crash of a different sort.
One of the possible problems here is that you are using strcpy
strcpy works by reading an array of characters until it reaches a null terminating character '\0' - However your source array does not contain a null terminating character. so strcpy will keep copying forever, reading memory it doesn't have access to, and writing past the end of your destination array, either of which could cause the crash. You need to either use strncpy (which you should always prefer), which only copies a fixed number of characters.
You should in general always leave an extra space in any character array if you intend on treating the characters as a string, like strcpy does. If you are only using individual elements and treating the individual characters on their own, then you don't need to. You could equally use memcpy in that case.
There may be other problems in the code, this is just one I have spotted.
You also have memory leaks, you should delete[] the member variables you new[]

Seg Fault when creating dynamic array of strings

My friend is writing a text-based game and asked me to look at this code that was crashing. I debugged it and it was getting a seg fault when creating a dynamic array. I'm not sure exactly why, I recommended he just avoid pointers altogether and use a vector so hopefully that will solve his problem but I'm curious as to what exactly is going wrong here. Here's his code:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;
class nation
{
public:
void init();
string genName();
string getName();
private:
string myName;
int* myBorderPoints;
};
string nation::getName()
{
return myName;
}
string nation::genName()
{
int listLength = 0, listPos = 0, listRand = 0;
string nameToGen = "";
string* namePartList;
ifstream fileName;
fileName.open("NamePart1.txt");
listLength = fileName.tellg();
namePartList = new string[listLength]; // Seg fault here
while (fileName.good())
{
while (!fileName.eof())
{
getline(fileName,namePartList[listPos]);
listPos += 1;
}
}
listRand = rand() % listLength;
nameToGen += namePartList[listRand];
fileName.close();
listLength = 0;
listPos = 0;
listRand = 0;
nameToGen = "";
fileName.open("NamePart2.txt");
listLength = fileName.tellg();
namePartList = new string[listLength];
while (fileName.good())
{
while (!fileName.eof())
{
getline(fileName,namePartList[listPos]);
listPos += 1;
}
}
listRand = rand() % listLength;
nameToGen += namePartList[listRand];
fileName.close();
return nameToGen;
}
void nation::init()
{
srand(time(NULL));
myName = genName();
}
int main()
{
nation testNation;
testNation.init();
cout << testNation.getName();
return 0;
}
You are calling tellg:
listLength = fileName.tellg();
without having read anything, which depending on whether the file was opening successfully or not will return 0 or -1 and so you will have this called:
namePartList = new string[listLength]
with a probably a undesirable value. I am pretty sure it is returning -1 since allocating a zero sized should be ok.
This also applies later on the code as well, going with std::vector probably makes more sense.