Crash in a C++ tutorial program (reading matrix) - c++

I am new to using C++ and Microsoft Visual Studio and I trying to convert a data file (2 columns by 500 rows consisting of floats) into an array, and then I am trying to output the array on screen. Whenever I try to run it, it comes up with "Unhandled exception at 0x001BC864 in file.exe: 0xC0000005: Access violation writing location 0x00320A20."
I found this video and tried to adapt that code https://www.youtube.com/watch?v=4nz6rPzVm70
Any help would be appreciated.
#include<stdio.h>
#include<string>
#include<iostream> //
#include<fstream> //
#include<array> //
#include<iomanip> //
#include<sstream>//
#include<conio.h>
using namespace std;
int rowA = 0; //
int colA = 0;
int main()
{
string lineA;
int x;
float arrayA[2][500] = { { 0 } };
ifstream myfile("C:/results.dat");
if (myfile.fail()) {
cerr << "File you are trying to access cannot be found or opened";
exit(1);
}
while (myfile.good()) {
while (getline(myfile, lineA)) {
istringstream streamA(lineA);
colA = 0;
while (streamA >> x) {
arrayA[rowA][colA] = x;
colA++; }
rowA++; }
}
cout << "# of Rows --->" << rowA << endl;
cout << "# of Columns --->" << colA << endl;
cout << " " << endl;
for (int i = 0; i < rowA; i++) {
for (int j = 0; j < colA; j++) {
cout << left << setw(6) << arrayA[i][j] << " ";
}
cout << endl;
}
return 0;
_getch();
}

Obviously your access to the array is out of bounds as you have your array indices go beyond the size of the array dimensions.
Given that this will not be the last time you run into this kind of problems, my answer will give you tips on how to detect if stuff like that goes wrong.
Your first tool on the rack is to add assertions to your code which make the problem evident in a debug build of your code.
#include <cassert>
// ...
while (myfile.good()) {
while (getline(myfile, lineA)) {
istringstream streamA(lineA);
colA = 0;
while (streamA >> x) {
// probably you would have noticed the error below while writing
// those assertions as obviously you would notice that you want 500
// rows and not 2 and you want 2 columns, not 500...
assert( rowA < 2 ); // <<--- This will assert!
assert( colA < 500 ); // <<--- This will assert if there are more than 500 lines in the file.
arrayA[rowA][colA] = x;
colA++; }
rowA++; }
With only those 2 extra lines (and the include), you would have been able to see where your code messes up.
In this case, fixing your code is quite easy and I leave it to you as an exercise ;)
In order to avoid mixing up the indices for your multi-dimensional array, you could write your code in a more suggestive manner (more readable).
int main()
{
string lineA;
int x;
const int NUM_COLUMNS = 2;
const int NUM_ROWS = 500;
float arrayA[NUM_COLUMNS][NUM_ROWS] = { { 0 } };
// ...
This tiny bit of extra expressiveness increases your odds to notice that your array access further below uses the wrong index variables per array dimension.
Last not least, you should add extra checks given that your program only works correctly (after fixing it) if the input file does not violate your assumptions (2 columns, less than 501 rows). This falls under the chapter of "defensive programming" - i.e. your code protects itself from violations of assumptions outside its scope of control.
You repeat your error in the print-loop at the bottom, btw. There, too you could add assertions.

Related

Having trouble on this assignment where we need to use pointers and arrays to find the average, median, and mode of some numbers in a text file

I'm having some issues when trying to read in the values from a text file. The text file looks like this:
Murray Brandl 3
Christal Delamater 4
Zetta Kinlaw 7
Elia Roy 3
Delmer Bibb 4
Joannie Nevers 4
Roselle Gose 10
Jonathan Basnett 0
Marcel Earwood 12
Marina Newton 2
Magdalen Stephan 3
Deane Leach 5
Mariana Crosley 6
Darby Froman 5
Shonda Kyzer 4
Ilana Netto 4
Candida Magnani 1
Laurena Stiverson 2
Elouise Muir 4
Rene Holiday 2
We need to read these names and values into variables while using pointers and arrays. I am getting some errors such as this:
"Exception thrown: read access violation.
_Pnext was 0xFDFDFE01. occurred"
I don't know what this means or where to look to fix it. Below you can see my attempt so far, but I've only gotten to the averageMovie function because I am unable to read the text file in correctly. If you could help me out or point me in the right direction I would really appreciate it!
#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
#include "Chapter 10 Movie Statistics.h"
using namespace std;
void averageMovie(int [], int);
int main()
{
ifstream infile;
infile.open("MovieStatistics.txt");
int numOfStudents = 0;
string first, last, line;
int movies;
int *numMovies;
string *names;
numMovies = new int[numOfStudents];
names = new string[numOfStudents];
if (!infile)
{
cout << "Error opening file";
}
else
{
while (getline(infile, line))
{
numOfStudents++;
istringstream ss(line);
ss >> first >> last >> movies;
}
for (int i = 0; i < numOfStudents; i++)
{
names[i] = first + last;
numMovies[i] = movies;
}
}
cout << "The number of students in the file is: " << numOfStudents << endl << endl;
averageMovie(numMovies, numOfStudents);
return 0;
}
void averageMovie(int array[], int size)
{
int total = 0,
average;
for (int i = 0; i < size; i++)
{
total += array[i];
}
average = total / size;
cout << "The average number of movies watched is: " << average;
}
int numOfStudents = 0;
// [snip]
int *numMovies;
string *names;
// [snip]
numMovies = new int[numOfStudents];
names = new string[numOfStudents];
Both of your arrays have zero elements; thus, every single access to them is broken. Increasing numOfStudents later makes no difference; it is too late.
What you're seeing is the technical result of utterly blasting your computer's memory.
Options:
Pick a number (e.g. 100) and use that; use up to 100 slots; stop the program before you go over that limit, though!
Precalculate how many you will actually need (one per line in the file, right?), then allocate the arrays
Use an array that expands on its own, i.e. a vector (though I'm betting your assignment does not permit this)

Corrupted array [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
char arr[10]="\0",arr1[2][5]={'\0'};
cout<<"enter the full line : ";
gets(arr);
for (int i=0;i<1;i++)
{
for (int j=0;j<10;j++)
{
if(j<=4)
{
arr1[0][j]=arr[j] ;
}
else if (j>4)
{
arr1[1][j-5]=arr[j] ;
}
}
}
for(int j=0;j<5;j++)
{
cout<<arr1[0][j]<<" ";
}
cout<<endl;
for(int j=0;j<5;j++)
{
cout<<arr1[1][j]<<" ";
}
Here what i am trying to do is converting a 1d array in to 2d array.
my main purpose is to store 1d array on a 2d and when the first row is completed it should shift the string to next row it is doing all the as i have declared the arr[10] and inputting 10 charcter string through get(arr) it is storing the array as i want but at the end displays an error window i dont know why the program is running perfect as well as giving this error window
my input : hanzlaamja (10charcters)
my output:
h a n z l
a a m j a
according to my wish but the main problem is the error window.
note : there is nothing in error box or warning box.
My program is working perfectly, but i am getting an error of array corruption.
Can anybody help me out? I would be very thankful
please see this error message
full picture
The problem is that you read in 10 characters (e.g. "hanzlaamja") and the string termination character '\0', which is automatically added by gets. Thereby you exceed array bounds, as this would require space for 11 characters. So it would already work if you wrote char arr[11];. But as mentioned in the comments, do not use gets; it is unsafe and it does not prevent you from exceeding array bounds. The following snippet shows how to do this part better:
...
char arr[11]="\0",arr1[2][5]={'\0'};
cout<<"enter the full line : ";
// gets(arr);
if (!fgets(arr,11,stdin)) {
cout << "no value read." << endl;
return 1;
}
...
A lot of your loops could be written shorter / better readable. But that's not the actual topic.
Adding to the great point pointed out by #Stephan Lechner, I have composed a solution "as close as possible" to your original.
Compiled under visual studio 2017.
#include "stdafx.h"
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
cout << "main - start" << endl;
const size_t numOfRows = 2;
const size_t numOfCol = 5;
const size_t numCharsInSingleDimArray = 10;
char arr[numCharsInSingleDimArray] = { '\0' }, arr1[numOfRows][numOfCol] = { '\0' };
cout << "enter the full line : ";
gets_s(arr); // Note:If the buffer (arr) is too small to contain the input line and null terminator, these functions invoke an invalid parameter handle.
cout << "main - entered:" << arr << endl;
char* twoDimArrStartLoc = &(arr1[0][0]); // as user4581301 pointed out, it is also possible to "approach" it by treating the two dimensional array as a contiguous bytes in memory
for (size_t i = 0, j = 0; i< numCharsInSingleDimArray; ++i, ++j)
{
twoDimArrStartLoc[j] = arr[i];
}
cout << "main - after converting the 1d array into 2d array, arr1 is:" << endl;
for (size_t i = 0; i < numOfRows; ++i)
{
for (size_t j = 0; j < numOfCol; ++j)
{
cout << "arr1[" << i << "]" << "[" << j << "]:" << arr1[i][j] << " ";
}
cout << endl;
}
// for debug - you can remove this if not needed...
cout << "main - end, enter any key and press enter to terminate..." << endl;
char tmp;
cin >> tmp;
return 0;
}
Hope it helps.
Cheers,
Guy.
thank you everyone for your support the MAIN mistake i was doing is the use of gets(arr) and doing arr[10] as if you are using function gets(arr) you have to give one extra index which is used by this function gets(arr) i.e. arr[11]
solved :)

how to convert an for loop to while loop c++

I'm trying to convert a for loop to while loop in c++ and do some checking for duplicates in a random number generator for generating lotto numbers so far all the stuff i'm trying seems to make the compiler very unhappy and I could really use a few pointers. It's the for loop in the Harray() function that feeds the Balls[] array
that i want to convert to a while loop.
#include<iostream>
#include<cstdlib> // to call rand and srand.
#include<ctime> // to make rand a bit more random with srand(time(0)) as first call.
#include<iomanip> // to manipulate the output with leading 0 where neccesary.
using namespace std;
// Hrand() function create and return a random number.
int Hrand()
{
int num = rand()%45+1; // make and store a random number change 45 for more or less Balls.
return num; // return the random number.
}
// Harray() function create and fill an array with random numbers and some formatting.
void Harray()
{
int Balls[6]; // change the number in Balls[6] and in the for loop for more or less nrs. a row.
for(int x=0; x<=6; x++) //the loop to fill array with random numbers.
{
int a; // made to pass the Balls[x] data into so i can format output.
int m = Hrand(); // calling the Hrand() function and passing it's value in int m.
Balls[x] = m; // throwing it into the array tought i did this because of an error.
a = Balls[x]; // throwing it into int a because of an type error.
cout<<"["<<setfill('0')<<setw(02)<<a<<"]"; //format output with leading 0 if neccesary.
}
cout<<endl; // start new row on new line.
}
// Main function do the thing if compiler swallows the junk.
int main() // start the program.
{
int h; // int to store user cchoice.
srand(time(0)); // make rand more random.
cout<<"How many rows do you want to generate?"<<endl; // ask how many rows?
cin>>h; // store user input.
for(int i=h; h>0; h--) // produce rows from user input choice.
{
Harray(); // calling Harray function into action.
}
return 0; // return zero keep the comipler happy.
}
I would like to always have six diffrent numbers in a row but i don't see how to get there with the for loops i think the while loop is way to go but am open to any suggestion that will work. I'm just starting with c++ i might have overlooked some options.
int x=0;
while(x<6)
{
int a;format output.
int m = Hrand();value in int m.
Balls[x] = m; because of an error.
a = Balls[x];
cout<<"["<<setfill('0')<<setw(02)<<a<<"]";
x++;
}
Here, I also fixed a bug. Since Balls has 6 elements, the last element will be 5. Thus you want x<6 instead of x<=6. That goes for the for loop too.
One drawback of while loops is that you cannot declare local variables with them.
First of all, you should realize that the difference between a for loop and a while loop is mostly syntactic--anything you can do with one, you can also do with the other.
In this case, given what you've stated as your desired output, what you probably really want is something like this:
std::vector<int> numbers;
std::set<int> dupe_tracker;
while (dupe_tracker.size() < 6) {
int i = Hrand();
if (dupe_tracker.insert(i).second)
numbers.push_back(i);
}
The basic idea here is that dupe_tracker keeps a copy of each number you've generated. So, you generate a number, and insert it into the set. That will fail (and return false in retval.second) if the number is already in the set. So, we only add the number to the result vector if it was not already in the set (i.e., if it's unique).
How convert for-loop to while-loop
#include <iostream>
class T545_t
{
// private data attributes
int j;
public:
int exec()
{
// A for-loop has 3 parameters, authors often fill 2 of them with magic
// numbers. (magic numbers are usually discouraged, but are expected
// in for-loops)
// Here, I create names for these 3 for-loop parameters
const int StartNum = 2;
const int EndNum = 7;
const int StrideNum = 2;
std::cout << std::endl << " ";
for (int i = StartNum; i < EndNum; i += StrideNum ) {
std::cout << i << " " << std::flush;
}
std::cout << std::flush;
// A while-loop must use / provide each of these 3 items also, but
// because of the increased code-layout flexibility (compared to
// for-loop), the use of magic numbers should be discouraged.
std::cout << std::endl << " ";
j = StartNum;
do {
if (j >= EndNum) break;
std::cout << j << " " << std::flush;
j += StrideNum;
} while(true);
std::cout << std::flush;
std::cout << std::endl << " ";
j = StartNum;
while(true) {
if (j >= EndNum) break;
std::cout << j << " " << std::flush;
j += StrideNum;
}
std::cout << std::flush;
std::cout << std::endl << " ";
j = StartNum;
while(j < EndNum) {
std::cout << j << " " << std::flush;
j += StrideNum;
}
std::cout << std::endl;
return 0;
}
}; // class T545_t
int main(int , char** )
{
T545_t t545;
return(t545.exec());
}
Ask me where 'j' is declared?
This code is marked as C++, so in this case, I have declared 'j' in the private data attribute 'section' of this class definition. That is where you'd look for it, right?
If your c++ code does not have class, what's the point?

Segmentation fault while reading a large array from a file. C++/gcc

In the following code I'm trying to find the frequencies of the rows in fileA which have the same value on the second column. (each row has two column and both are integers.) Sample of fileA:
1 22
8 3
9 3
I have to write the output in fileB like this:
22 1
3 2
Because element 22 has been repeated once in second column(and 3 repeated 2 times.)
fileA is very large(30G). And there are 41,000,000 elements in it(in other words, fileB has 41,000,000) rows. This is the code that I wrote:
void function(){
unsigned long int size = 41000000;
int* inDeg = new int[size];
for(int i=0 ; i<size; i++)
{
inDeg[i] = 0;
}
ifstream input;
input.open("/home/fileA");
ofstream output;
output.open("/home/fileB");
int a,b;
while(!input.eof())
{
input>>a>>b;
inDeg[b]++; //<------getting error here.
}
input.close();
for(int i=0 ; i<size; i++)
{
output<<i<<"\t"<<inDeg[i]<<endl;
}
output.close();
delete[] inDeg;
}
I'm facing segmentation fault error on the second line of the while loop. On the 547387th iteration. I have already assigned 600M to the stack memory based on this. I'm using gcc 4.8.2 (on Mint17 x86_64).
Solved
I analysed fileA thoroughly. The reason of the problem as hyde mentioned wasn't with hardware. Segfault reason was wrong indexing. Changing the size to 61,500,000 solved my problem.
In the statement:
while(!input.eof())
{
input>>a>>b;
inDeg[b]++;
}
Is b the index of your array?
When you read in the values:
1 22
You are discarding the 1 and incrementing the value at slot 22 in your array.
You should check the range of b before incrementing the value at inDeg[b]:
while (input >> a >> b)
{
if ((b >= 0) && (b < size))
{
int c = inDeg[b];
++c;
inDeg[b] = c;
}
else
{
std::cerr << "Index out of range: " << b << "\n";
}
}
You are allocating a too huge array in to the heap. It´s a memory thing, your heap cant take that much space.
You should split your in and output in smaller parts, so at example create a for loop which goes every time 100k , deletes them and then does the next 100k.
in such cases try a exception handling, this is a example snippet how to manage exception checking for too huge arrays:
int ii;
double *ptr[5000000];
try
{
for( ii=0; ii < 5000000; ii++)
{
ptr[ii] = new double[5000000];
}
}
catch ( bad_alloc &memmoryAllocationException )
{
cout << "Error on loop number: " << ii << endl;
cout << "Memory allocation exception occurred: "
<< memmoryAllocationException.what()
<< endl;
}
catch(...)
}
cout << "Unrecognized exception" << endl;
{

Segmentation fault on creating matrices

I was practicing on c++ on some tutorials and I encountered on a tutorial that creates matrices, I wanted something more from it and I modified it, I dont know matrices at all cuz I didnt learn them yet at school but this code below sometimes works sometimes not.
When it doesn't work I usually get: Segmentation fault.
why does this happen ?
before it happened everytime but after i gave a 0 value to variable line and member on the beginning it doesnt happen anymore, but still if I type exc
Line: 10
Member: 9
it gives:
1 1 1 1 1 1 1 1 1
1 2 3 4 5 1 7 8 9
Segmentation fault
and stopes.
Can anyone explain me this ?
thank you !
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int line=0,member=0;
int i,j,matrice[line][member];
cout << "\nLine: ";
cin >> line;
cout << "Member: ";
cin >> member;
cout << "\nCreated Matrice: \n" << endl;
for (i=0;i<line;i++)
{
for (j=0;j<member;j++)
{
matrice[i][j]=i*j+1;
cout << setw(5) << matrice[i][j];
}
cout << "\n\n";
}
return 0;
}
int line=0,member=0;
int i,j,matrice[line][member];
This line shouldn't compile. In standard C++,
arrays of 0 size are not allowed
array sizes must be constant expressions
It appears that your compiler allows these as extensions. In any case when you later input line and member your array size doesn't change. You should define your array after you've input these numbers. But the array must be dynamically allocated (better yet, use vectors)
#include <vector>
//...
int line, member;
cin >> line >> member;
vector<vector<int> > matrix(line, vector<int>(member));
or if you don't want to use vector for educational purposes, do this:
int line, member;
int ** matrix;
cin >> line >> member;
matrix = new int*[line];
for(int i = 0; i < line; ++i)
matrix[i] = new int[member];
Don't forget to free the matrix.
for(int i = 0; i < line; ++i)
delete [] matrix[i];
delete [] matrix;
I suggest that you should read a good C++ book
HTH
The matrice array is initialized with a size of [0][0], which are the values of line and member. Since you override the values with the inputted values, the bounds used in the for loops are invalid.
i.e. You are accessing items out of the array's bounds.
You may want to use new to dynamically create arrays, or just use std::vector which resizes itself.
Also, it is not standard, but if your compiler supports it, you can use variable-length arrays. They behave like regular arrays but are allocated using a runtime-computed value :
int line=0,member=0;
int i,j;
cout << "\nLine: ";
cin >> line;
cout << "Member: ";
cin >> member;
int matrice[line][member];
You should also check for the inputted values, since C++ does not allows zero-size arrays (And it wouldn't make sense in your program anyway.)
You are using dynamic array without allocating memory using malloc or similar. That is in your line int i,j,matrice[line][member]; is not an array with constant size thus memory should be dynamically allocated. Or use a constant matix size as poster above suggested.
I agree with other comments that using vectors is a much safer way to solve your problem: using arrays directly is definitely error-prone. Of course, if your exercise requires using arrays, then you should use arrays.
Regarding the performance, I have written a small test using g++ on Ubuntu 10.04. Running
g++ --version
I get
g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3
My test program creates a 100x100 matrix and sets each element to some value. It first has a few declarations:
#include <vector>
#include <iostream>
#include "util.h" // Timer utilities.
#define LINE_COUNT (100) // The number of lines.
#define COL_COUNT (100) // The number of columns.
#define REPETITIONS (100000) // Number of repetitions for each test.
using namespace std;
Then I have the test using vectors:
void use_vectors()
{
int line = LINE_COUNT;
int member = COL_COUNT;
vector<vector<int> > matrix(line, vector<int>(member));
// Set data.
for (int i = 0; i < line; i++)
{
for (int j = 0; j < member; j++)
{
matrix[i][j] = -5;
}
}
}
Then I have a function to perform the same test (create matrix and set values) using arrays:
void use_arrays()
{
int line = LINE_COUNT;
int member = COL_COUNT;
int **matrix;
matrix = new int * [line];
for (int i = 0; i < line; i++)
{
matrix[i] = new int[member];
}
// Set data.
for (int i = 0; i < line; i++)
{
for (int j = 0; j < member; j++)
{
matrix[i][j] = -5;
}
}
for (int i = 0; i < line; ++i)
{
delete [] matrix[i];
}
delete [] matrix;
}
The main program repeats both tests, and records the time needed for each of them. Here is the main program:
main()
{
long int es = 0;
long int eu = 0;
start_timer();
for (int i = 0; i < REPETITIONS; i++)
{
use_vectors();
}
stop_timer();
es = elapsed_sec();
eu = elapsed_usec();
cout << "Vectors needed: " << es << " sec, " << eu << " usec" << endl;
start_timer();
for (int i = 0; i < REPETITIONS; i++)
{
use_arrays();
}
stop_timer();
es = elapsed_sec();
eu = elapsed_usec();
cout << "Arrays needed: " << es << " sec, " << eu << " usec" << endl;
}
The timer functions are based on the library function gettimeofday() (see e.g. http://linux.die.net/man/2/gettimeofday).
The result is the following:
Vectors needed: 24 sec, 624416 usec
Arrays needed: 10 sec, 16970 usec
So it seems that vectors do have some overhead wrt to arrays. Or can I do something to improve the performance of vectors? I checked my benchmark code a few times and it seems to me I got it right.
Anyway, I would by no means advise using arrays just to gain performance unless it really makes a big difference in your application.
You want to allocate memory dynamically.
Then, Use Dynamic allocation like this:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int line=0,member=0;
int i,j;
int **matrice; //Define matrice as a 2D array(a Matrix)
cout << "\nLine: ";
cin >> line;
cout << "Member: ";
cin >> member;
//start of dynamic allocation
matrice=new int*[line];
for (i=0;i<line;i++)
matrice[i]=new int[member];
//End of dynamic allocation
cout << "\nCreated Matrice: \n" << endl;
for (i=0;i<line;i++)
{
for (j=0;j<member;j++)
{
matrice[i][j]=i*j+1;
cout << setw(5) << matrice[i][j];
}
cout << "\n\n";
}
delete[] matrice; //Releasing allocated memory
return 0;
}