Segmentation Fault while accessing 2-dimensional vector - c++

I am trying to access a specific position of a 2-dimensional vector. I declared the vector and initialized it, and on printing it out, the vector seems properly declared. Now, when I try to access the vector from an if statement in a class function, I get a segmentation fault.
class cache{
vector<vector<int>> v;
v.resize(5);
for(z = 0; z < v.size(); z++){
v[z].resize(5);
}
for(x = 0; x < v.size(); x++){
for(y = 0; y < v[x].size(); y++){
v[x][y]=5;
}
}
for(x = 0; x < v.size(); x++){
for(y = 0; y < v[x].size(); y++){
cout<<v[x][y]<<" ";
}
cout<<"\n";
}
int readCache(int a){
int value = a>>15;
int index = a % (unsigned long)pow(2,15);
// Do I not try to access using the size?
for(x = 0; x < v.size(); x++){
cout<<v[x][index]<<endl;
// Or do I use this alternate line?
// cout<<v[index][x]<<endl;
}
}
};
I can't find a proper error message either.
The vector's sizes change depending on the parameters passed to it.
For now, its a 1x2048 vector.

Simple out of bound access. You have a 5x5 matrices, but you are trying to get an element outside:
int value = a>>15;
int index = a % (unsigned long)pow(2,15); // This is also very not efficient
The index is most definitely wrong.

EDIT 2: Segmentation Faults appear to be fixed.
Since this is a homework question, I am unable to post the complete online for fear of plagiarism issues.
However, the readCache function essentially checks if the address value is present in the nested vector. Now, it seems you cannot directly compare like
vec[a][b] = value;
It worked when I assigned the value at the desired position to a temporary variable and then compared to the given value. Like this:
int temp = vec[a][b];
if(temp == value){
// do something
}
EDIT: This hasn't worked yet.
#PaulMcKenzie's comment about accessing vectors helped me get rid of segmentation faults and I started running into out_of_range errors as they predicted.
Then, in the readCache function, I was passing a 32-bit bitset to access a cache. But I don't actually need to access the data byte in a cache block, so the modulus had three extra bits which I didn't need. The range of the modulus function is 0 to (value - 1), so at some point it would exceed the size of the vector.
It is a homework problem.

Related

Getting a C++ segmentation fault

I'm in a linux server and when I try to execute the program it's returning a segmentation fault. when i use gdb to try and find out why, it returns..
Starting program: /home/cups/k
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401128 in search(int) ()
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.192.el6.x86_64 libgcc-4.4.7-17.el6.x86_64 libstdc++-4.4.7-17.el6.x86_64
I couldn't quite interpret this. In my program i have a function called "search()" but i don't see anything that would cause a seg fault. here's the function def:
int search (int bit_type) { // SEARCH FOR A CONSEC NUMBER (of type BIT_TYPE) TO SEE IF ALREADY ENCOUNTERED
for (int i = 1; i <= MAX[bit_type]; i++) { //GO THRU ALL ENCOUNTERED CONSEC NUMBERS SO FAR (for type BIT_TYPE)
if (consec == r[bit_type][i]) // IF: FOUND
return i; // -----> RETURN INDEX OF RECORDED CONSEC_NUM
}
// IF: NOT FOUND
r[bit_type][++MAX[bit_type]] = consec; // -----> INCREMENT MAX[bit_type] & RECORD NEW CONSEC_NUM -------> ARRAY[MAX]
n[bit_type][MAX[bit_type]] = 1;
return (MAX[bit_prev]); // -----> RETURN THE NEWLY FILLED INDEX
}
global functions:
int MAX[2];
int r[2][200];
int n[2][200];
The comments are pretty useless to you guys since you don't have the rest of the program.. but you can just ignore them.
But do you guys see anything I missed?
From the link to your code here, here is just one error:
int *tmp = new int[MAX[0]];
for (int y = 0; y <= MAX[0]; y++) {
tmp[y] = 1;
}
You are going out-of-bounds on the last iteration. You allocated an array with MAX[0] items, and on the last iteration you're accessing tmp[MAX[0]].
That loop should be:
int *tmp = new int[MAX[0]];
for (int y = 0; y < MAX[0]; y++) {
tmp[y] = 1;
}
or better yet:
#include <algorithm>
//...
std::fill(tmp, tmp + MAX[0], 1); // no loop needed
or skip the dynamic allocation using new[] and use std::vector:
#include <vector>
//...
std::vector<int> tmp(MAX[0], 1);
In general, you have multiple loops that do this:
for (int i = 1; i <= number_of_items_in_array; ++i )
and then you access your arrays with array[i]. It is the <= in that for loop condition that is suspicious since it will try to access the array with an out-of-bounds index on the last iteration.
Another example is this:
long sum(int arr_r[], int arr_n[], int limit)
{
long tot = 0;
for (int i = 1; i <= limit; i++)
{
tot += (arr_r[i])*(arr_n[i]);
}
return tot;
}
Here, limit is the number of elements in the array, and you access arr_r[i] on the last iteration, causing undefined behavior.
Arrays are indexed starting from 0 and up to n - 1, where n is the total number of elements. Trying to fake 1-based arrays as you're attempting to do almost always results in these types of errors somewhere inside of the code base.

Using comparison operators to sort string array

I looked everywhere and I could not find a concrete answer that suits my needs. I want use this type of format to sort a more complicated array than this example. It compiles, but when I run it I get the terminated by signal SIGSEV (address boundary error).
A simple example of what I am trying to do:
string array[] = {zipper, bad, dog, apple, car};
string temparray[5];
int counter = 0;
for(int i = 0; i < 5; i++){
for(int x = 0; x < 5; x++){
if(array[i] > array[x]){
counter++;
}
}
temparray[counter] = array[i];
}
for(int y = 0; y < 5; y++){
array[y] = temparray[y];
}
What seems to be the problem?
You never reset counter. Suppose that your array is {5,4,3,2,1}. Then after the first iteration of the for loop, you'd have counter=4. After the next iteration of the inner for loop, counter would be 7, and you'd be trying to access the 7th element in temparray on your line
temparray[counter] = array[i];
but temparray is only 5 elements long. I don't offhand know how the > and < operators work for std::string's, but I'd bet oaks to acorns this is your problem.
You can fix this just by adding
counter=0;
directly after the aforementioned line:
temparray[counter] = array[i];
or by initializing it to zero at the start of the loop, or declaring it in the loop or what have you.

Initializing a member vector<vector<int>> in the constructor value-by-value

I have a class that should generate a 2D vector of ints (in the range of 0-1) that I want to use as a map (called matrix).
class generator
{
public:
void draw(void);
void iterate(void);
generator();
~generator();
private:
vector<vector<int>> matrix;
};
In the constructor I want to fill the matrix with random data:
vector<vector<int>> matrix(height, vector<int>(width));
for (int i = 0; i < height; i++){
for (int j = 0; j < width; j++) {
matrix[i][j] = rand() % 2;
}
}
But I get a read acess violation.
Thank you for your time and effort.
DEPRECATED UPDATE:
I tried using the member function .data() to retrieve the pointer to the data and accessing it directly
ptr = matrix[i][j].data();
*ptr = rand() % 2;
But the result doesn't differ. I'm fairly convinced that this isn't about how I want to access the vector but how I set it up.
UPDATE 2:
The correction provided below does result in the vector being filled as intended. When trying to
cout << matrix[i][j];
in the draw member function I get a read-acess-violation again.
UPDATE 3:
As suggested I checked when exactly this error happens. It happens on the very first try do print out the first integer at matrix[0][0]. The value returned is 0x8. Important: If not replaced by a constant matrix.size() already causes the error.
UPDATE 4:
This is basically my draw()
void generator::draw() {
for (int i = 0; i < matrix.size(); i++) {
for (int j = 0; j < matrix[i].size(); j++) {
cout << matrix[i][j];
}
cout << endl;
}
}
The original source has been updated to reflect the current one.
UPDATE 4:
Slightly cut source code at http://pastebin.com/83vrDJWZ
UPDATE 5:
One more simple mistake on my part has been resolved in the comments. Problem is silved. Thank you all.
Looks like the problem is an invalid pointer due to:
vector<vector<int>*> matrix;
You have a vector of pointers to vector of int, but you never actually allocate the inner elements.
Instead use:
vector<vector<int>> matrix;
And during the initialization steps:
matrix[i].resize(width); // instead of: matrix[i]->resize(width);
Actually, you could simplify it a bit:
std::vector<std::vector<int>> matrix(height, std::vector<int>(width));
Still have to iterate to fill the data, though.

how to add elements to front of 2d vector

I have a game that creates a random string of letters and then inputs it to a 2d vector. I was oringally using an array and it filled the array with random letters as it should, but the array was giving me some problems. My friend suggested a 2d array.
Here is the print function that gives me the error that actually causes a break in the program:
const vector<vector<char>>& Board::get_board()
{
for (int i = 0; i < 16; i++)
{
letters.insert(letters.begin(), 1, random_letter());
}
uppercase(letters);
random_shuffle(letters.begin(), letters.end());
int counter = 0;
for (size_t i = 0; i < 4; i++){
for (size_t j = 0; j < 4; j++)
{
board[0].push_back(letters[counter++]);
}
}
I keep getting the array to fill the first row, but then it throws an exception. I'm not sure what the exception is, but when I try to move forward, it tells me the code exited with exception 0 and points to the board[][] line in the print method. I don't think the second vector is being filled. How can I do this? Should I make another temp vector, or use a pair method? I tried the pair method before without much success.
I just changed the 0 to i and indeed, that solved the issue. Thanks! I think that I was thinking the vector would just push to the front counter number of times, not that we had 2 dimensions where the board[i] set the row. Thanks again. Silly error.
Your vector isn't being populated correctly in your get_board() method:
board[0].push_back(letters[counter]);
You're always pushing back onto the first element, but then you use it with the expectation that the board vector has 4 entries in it with the print() method. You also never increment counter and so you always push back the same letter...
Okay, based on comments, you've said you fixed how populate to something more like?
int counter = 0;
for (size_t i = 0; i < 4; i++){
for (size_t j = 0; j < 4; j++)
{
board[i].push_back(letters[counter++]);
}
}
I also don't see the point of the if statement in the print() method.

C++ Vector of vectors, cannot edit

I have a MatrixGraph class with a member variable M that is of type vector<vector<double> >. I have a constructor that takes in an unsigned, and makes a NxN matrix from that input, and I want to initialize it to zero. The problem is when I run my code the debugger kicks in when I am trying to assign stuff. I have tried to methods, the first:
MatrixGraph::MatrixGraph(unsigned num_nodes) {
for(int i = 0;i < num_nodes;i++) {
for(int j = 0;j < num_nodes;j++) {
M[i][j] = 0.0;//breaks on this line
}//end i for loop
}//end j for loop
}
and the second method i tried i found on here but that didn't work either:
MatrixGraph::MatrixGraph(unsigned num_nodes) {
for(int i = 0;i < num_nodes;i++) {
M[i].resize(num_nodes);//breaks on this line
}
}
i commented on here where the last line on the call stack is before i get errors. The next line after that on the call stack shows me the class vector and is saying that my Pos is greater than the size of my vector. I assume that this is a size zero matrix, but i don't know why i cant make it bigger. Any suggestions?
Thanks!
The reason your code is failing is that you cant use the [] operation on a vector before that element exists. The usual way to add a value to a vector is to use push_back.
If you want to initialize to 0 you want assign(). Resize the outer vector to the required size and then assign each of the inner vectors with 0
M.resize(num_nodes);
for(int i = 0;i < num_nodes;i++)
{
M[i].assign(num_nodes,0.0f);
}//end i for loop
This can also be done. It is cleaner code but a tad less efficient since it makes 1 extra vector object.
vector<double> temp;
temp.assign(num_nodes,0.0);
M.assign(num_nodes,temp);
or just
M.assign(num_nodes,vector<double>(num_nodes,0.0));
neatest one(courtesy #Mike Seymour) would be
MatrixGraph(unsigned num_nodes)
: M(num_nodes, vector<double>(num_nodes,0.0))
{}
(thanks Mike Seymour for the constructor syntax)
What you are doing here is initializing the outer vector with a temp vector full of 0.0s
You need to populate your vector M with data: M.resize(num_nodes)
This should do it:
MatrixGraph::MatrixGraph(unsigned num_nodes)
{
M.resize(num_nodes);
for(int i = 0;i < num_nodes;i++)
{
M[i].resize(num_nodes);
for(int j = 0;j < num_nodes;j++)
{
M[i][j] = 0.0;
}//end j for loop
}//end i for loop
}