My code segfaults on the last line here:
Level level1;
level1.generateLevel();
list<Entity>* obstacles;
//Get level obstacles
obstacles = level1.obstacleList;
Obviously there's something wrong with the way I handle the list, but I'm not sure what exactly. This is the code that handles the list.
for (int row = 0; row<6; row++)
{
level_position_x = -128;
for (int column = 0; column<8; column++)
{
level_position_x = level_position_x + tile_offset;
if (room_array[row][column] == 1)
{
obstacleList->push_front(*new Obstacle("images/ground.png", level_position_x, 768 - level_position_y - tile_offset));
}
}
}
I know that when dealing with arrays like I have in my for loop that they're often the source of crashes, but I'm fairly certain that with the rest of my code that room_array isn't the culprit. Is there something immediate that I'm missing that's causing this?
Related
A homework assignment for an introductory C++ course.
The task is to search a two dimensional array for two numbers adding up to a given number 'search_sum.' Enter all found addends as {startRow,startColumn,endRow,endColumn} in the array 'summations,' then return the array 'summations'.
The line with summations[*sums_found] = new size_t[kIndices_size]; in the if statement was written by the instructor, as well as the comment. I am under the impression that this allocates a new space in memory where data can be assigned to and stored, so, in the next line of code, I attempted to take the column and row variables from the for loop and place them in the newly allocated memory as such.
summations[*sums_found]={startRow, column, endRow, column};
This threw a 'too many assignments' and 'segmentation fault' error.
I assumed you just could not do it this way, and data must be added to a 2D array in another fashion. I removed the faulty assignment code and ran the code as shown below through a debugger, just out of curiosity. The error thrown was once again a Segmentation Fault.
// Parameters:
// - matrix: a two-dimension integer array
// - matrix_size: a two-element size_t array storing sizes of matrix
// - search_sum: the integer value for which the function seeks sums
// - sums_found: an OUTPUT PARAMETER pointing to a size_t
//
const size_t** FindSum(const int** matrix,
const size_t* matrix_size,
int search_sum,
size_t* sums_found) {
*sums_found = 0; // init sums found to 0
size_t summations_size = 2; // start assuming no more than 2 summations
// build structure to hold all found summations
size_t** summations = new size_t*[summations_size];
switch (search_sum)
{
case -92:{ //column search
for(size_t column = 0; column < matrix_size[1]; column++){
for(size_t startRow = 0; startRow < matrix_size[0]; startRow++){
for(size_t endRow = 0; endRow < matrix_size[0]; endRow++){
int j = matrix[startRow][column];
int k = matrix[endRow][column];
int sum = j + k;
if(sum = search_sum){
summations[*sums_found] = new size_t[kIndices_size]; // only done when summation is found
*sums_found++;
}
}
}
}
}
break;
case 60:{ //row search
for(size_t row = 0; row < matrix_size[0]; row++){
for(size_t startColumn = 0; startColumn < matrix_size[1]; startColumn++){
for(size_t endColumn = 0; endColumn < matrix_size[1]; endColumn++){
int j = matrix[row][startColumn];
int k = matrix[row][endColumn];
int sum = j + k;
if(sum = search_sum){
summations[*sums_found] = new size_t[kIndices_size]; // only done when summation is found
*sums_found++;
}
}
}
}
}
break;
case 1203:{ //desc/ascending diagonal
}
break;
case 412:{ //single entry
}
break;
default:{ //large array
}
break;
}
return const_cast<const size_t**>(summations);
}
I did not know what this was, so I researched the error and found that you are not allowed to perform a read/write action on read-only code, which makes sense. What I do not understand is what exactly makes this code read-only, when it seems like its function is to assign a new space for data to be assigned to, which (to me), sounds like a 'write-like' action? I more than likely am misunderstanding the full scope of the codes function, and I am further confused with as to how I should go about assigning the data to the summations array.
Also, this is a university course taught by a grad student who is (seemingly) less than well versed in c++. It is a very 'teach yourself' type class. I understand that this assignment is an exercise on pointers and references, but it feels like I am very poorly equipped to solve a problem like this, and I am unsure what exactly to research and study independently to improve my knowledge of this particular topic. Please, if you can tell what it is I am struggling with just by looking at the code I've written, let me know what I should prioritize my studying on.
I am trying to go through a txt file with facebook data from 2009 and represent people as vertices on a graph, and friendships as edges. The code to make the graph works perfectly. I used it to calculate the average number of friends that people in this data set had. But when trying to find the average of the average of their friends things get weird. When I try to get the number of friends of a certain friend, the size of that table drastically increases (one time it went from 10 to 988) it keeps doing this until I get a bad_alloc error and im not sure why. How can I access an element without it changing the graph?
while (FacebookInfo >> V1 >> V2 >> garbage) {
unordered_map<int, int>::const_iterator got = graph[V1].find(V2);
if (got == graph[V1].end()) {
graph[V1].insert(make_pair(V2, (int)graph[V1].size()));
graph[V2].insert(make_pair(V1, (int)graph[V2].size()));
}
}
//This is the loop that breaks it
for (int i = 1; i < 63732; i++) {
int averageFriendsOfFriendsForV = 0;
for (int j = 0; j < graph[i].size(); j++) {
int friendOfFriend = graph[graph[i][j]].size(); //this is the line specifically the graph[i][j]
averageFriendsOfFriendsForV += friendOfFriend;
}
averageFriendsOfFriendsForV /= graph[i].size();
totalAvg += averageFriendsOfFriendsForV;
}
Edit: Figured it out, still not sure why it would add data but
for(auto& j : graph[i]){
int friendOfFriend = graph[j.first].size();
etc...
}
fixes it
This always trips me up, if you take a look at the index operator for std::unordered_map, you'll find that it will:
... perform an insertion if such key does not already exist.
So in that loop on the line you suspect:
int friendOfFriend = graph[graph[i][j]].size();
you're probably creating new entries every time which eventually becomes impossible. If you post a bit more code it may be easier to diagnose (since I'm not sure what type graph is in the first place).
Instead of using the operator[], it might be good to do something like:
auto friend = graph.find(i);
if (friend == graph.end()) return;
auto other_friend = graph.find(friend->second);
if (other_friend == graph.end()) return;
or something along those lines where you explicitly check for the existence of the friend.
While performing a selection sort in a C++ homework assignment, the array I'm using is having issues sorting data into exactly the right positions. I'm particularly confused as in last week's assignment, I was able to successfully sort two arrays at the same time with the correct order -- however, this week, there are pointers involved, though I'm fairly certain that shouldn't affect a sort referencing just the elements themselves.
So far, I've tried entering the following data in many different entry orders:
1000
500
560
750
1200
The loading seems to be fine referencing the actual putting-data-in, and the sort appears to be sorting some numbers properly (putting 500 first, for instance, most of the time), but I'm clearly doing something incorrectly for it to be failing to sort. I'll show some entries and outputs below.
Here's the code for my selection sort itself:
void selectionSort(int rentArray[], int arrayElements)
{
int minSort = 0;
int sortHold;
sortHold;
for (int x = 0; x < arrayElements - 1; x++)
{
sortHold = rentArray[x];
for (int y = x + 1; y < arrayElements; y++)
{
if (rentArray[y] < sortHold)
{
minSort = y;
sortHold = rentArray[y];
}
}
if (minSort != x)
{
sortHold = rentArray[x];
rentArray[x] = rentArray[minSort];
rentArray[minSort] = sortHold;
}
}
}
Naturally, I expect the output to go from anything to sort the array into [500, 560, 750, 1000, 1200] rather than what it's going to. Some screenshots:
https://i.imgur.com/evATWAy.png https://i.imgur.com/dzcZiAl.png
EDIT: Thank you to both #Akiva and #6502 for the help!
Putting a quick minSort = x; into the function just under sortHold = rentArray[x]; solved the problem.
In case no element is lower than sortHold you'll still check minSort for being different from x but it will be the minSort from last iteration making your code doing a wrong swap.
You need to reset minSort where you reset sortHold (minSort = x)
I am using Predefined style -> Allman braces and this is the strange behavior I get:
// this looks good
int edges = 0;
long variable_2 = 0;
AnotherLong obj = 0;
// this looks bad way off
int edges = 0;
long variable_1;
long variable_2 = 0;
AnotherLong obj = 0;
The variables should be grouped in columns, however an empty line should indicate a new "block" of code, right ? On the first case int edges = 0; is aligned fine, why not in the second case ? How can I fix that ?
Edit: Created a bug report
CString dance[] = {L"Atb", L"Tiesto", L"Madonna", L"Paul van Dyk", L"Armin van Burren", L"Jennifer Lopez"};
for(int i = 0; i < m_ItemsListBox.GetCount(); ++i)
{
CString item;
int length = m_ItemsListBox.GetTextLen(i);
m_ItemsListBox.GetText(i, item.GetBuffer(length));
for(int j = 0; j < sizeof(dance)/sizeof(*dance); ++j)
{
if(item != dance[j])
{
m_ItemsListBox.DeleteString(i);
}
}
}
I'm trying to remove from a listbox(m_ItemsListbox) all elements that are not part from the CString array. But how I coded it doesnt work, because if the first element its different it will delete it without searching the entire array.
Doesn't seemed like a hard task but I really have no idee how to do it. I think one way should be to use a CList instead of the array because it has a find() method, but I don't like it because I have to manually add all the elements, do you guys have another idee? Or the CList solution is the only one ?
Sorry, I'm a MFC begginer. Thanks for your time.
Hmmm I wouldn't be comfortable deleting things from the list box while iterating through the items in the listbox seems to be asking for problems down the line.
Honestly you could do something like this, I've just whipped together - construct a list of all the item indexes you want to remove and remove them at the end.
CList<int, int> ListIndexItemsToRemove;
for(int i = 0; i < m_ItemsListBox.GetCount(); ++i)
{
CString item;
int length = m_ItemsListBox.GetTextLen(i);
m_ItemsListBox.GetText(i, item.GetBuffer(length));
bool isMatchFound = false;
for(int j = 0; j < sizeof(dance)/sizeof(*dance); ++j)
{
if(item == dance[j])
{
isMatchFound = true;
}
}
if (!isMatchFound)
ListIndexItemsToRemove.AddHead(i);
}
for(int i = 0; i < ListIndexItemsToRemove.GetCount(); ++i)
m_ItemsListBox.DeleteString(ListIndexItemsToRemove.GetAt(ListIndexItemsToRemove.FindIndex(i));
but - it may be better to clear the whole list and refill it everytime something changes, as Martin says (if it doesn't affect anything.
For dynamic lists I tend to store data in its own variable and clear/re-populate the list when that data changes. Especially as the list gets bigger re-adding the strings tends to be much faster than doing searches through the list and/or original source.