I am getting a "Segmentation fault (core dumped)" run-time error with the following code:
#include <iostream>
#include "Student.h"
#include "SortedList.h"
using namespace std;
#define BOUNDS 100
int main() {
SortedList *list = new SortedList(); // points to the sorted list object
Student *create[BOUNDS]; // array to hold 100 student objects
int num = 100000; // holds different ID numbers
// fills an array with 100 students of various ID numbers
for (int i = 0; i < BOUNDS; i++) {
create[i] = new Student(num);
num += 10;
}
// insert all students into the sorted list
for (int i = 0; i < BOUNDS; i++)
list->insert(create[i]);
// individually deletes each student
num = 100000;
for (int i = 0; i < BOUNDS; i++) {
delete list->find(num);
num += 10;
}
// insert all students into the sorted list
for (int i = 0; i < BOUNDS; i++)
list->insert(create[i]);
num = 100000;
for (int i = 0; i < BOUNDS; i++) {
list->remove(num);
num += 10;
}
cout << "test2" << endl;
delete list;
return 0;
}
I have narrowed the error down to the delete list; lines (or whichever one comes first). I am just wondering as to why this is and how to possibly fix it. Any insight on this matter would be useful.
You have two problems that I can see.
First, in this loop:
for (int i = 0; i < BOUNDS; i++) {
x = new Student(num);
num += 10;
}
You are creating a bunch of dynamic Students and putting the latest one in x and the previous one is lost. This creates 100 Students dynamically and 99 of them are leaked. Also it doesn't fill an array with Students like the comment above it says it does. I'm not sure what you're trying to do here so I can't comment on what you need to do instead.
Secondly, you are calling delete here:
delete list->find(num);
on Students that are in automatic storage (the stack) (because you filled the list with pointers to the Students in create which holds automatic Students), which leads to undefined behaviour and is probably the cause of your segfault. You don't need to deallocate these Students because they will be deallocated when the array goes out of scope at the end of main.
Without knowing how StudentList is implemented, this is kind of shot in the dark but...
list->insert(&create[i]); is adding a stack allocated object to the list, and then delete list->find(num); tries to delete this stack allocated object. You can't delete stack allocated objects.
In addition to this, your first for loop is leaking memory.
And I've been ninja'd.
This line has a problem:
list->insert(&create[i]);
At that point, create has been allocated, but nothing has been put into it. Probably the result of x = new Student(num) should be assigned there.
"create" array is allocated on stack. You are trying to delete stack allocated memory that's why you getting this error.
delete list->find(num);
You are definitely leaking memory:
// fills an array with 100 students of various ID numbers
for (int i = 0; i < BOUNDS; i++) {
x = new Student(num);
num += 10;
}
The x is leaked in this snippet, unless the ctor of Student somehow magically inserts itself somewhere, where the pointer can be tracked.
And that might or might be related to the crash.
Related
2D Array creation phase :
int **table = new int*[10];
for (int a = 0; a < 10; a++)
{
table[a] = new int[10];
for(int b = 0; b < 10; b++){
table[a][b] = 0;
}
}
2D Array deletion phase :
for (int i = 0; i < 10; i++)
{
delete [] table[i];
}
delete [] table;
I noticed something while debugging my code with GDB. All values from table[0][0] to table[0][3] are garbage but all values from table[0][4] to table[0][9] are all 0. This problem is Valid for all pointers from table[0] to table[9].
Then I thought there was a problem with GDB and I printed table[0][0] and table[0][5] to the screen. Indeed the value of table[0][0] is garbage, the value of table[0][5] is 0.
My question is does c++ actually freeing this data?
Yes, the data is actually being freed. If you dereference a pointer after its value is freed, you get undefined behaviour which might be its original value or some other garbage value.
I have an array of pointers:
Hotel *hotels[size];
for (int i = 0; i < size; ++i)
hotels[i] = new Hotel();
And I want to insert an object in this array after some object with name I know:
cin >> tmp_name;
for (int i = 0; i < size; i++) {
if (hotels[i]->get_name() == tmp_name) {
hotels[size] = new Hotel();
size += 1;
Hotel *tmp_hotel;
tmp_hotel = hotels[i+1];
hotels[i+1]->fillHotel();
for (i = i + 2; i < size; i++) {
hotels[i] = tmp_hotel;
tmp_hotel = hotels[i+1];
}
break;
}
}
What I do wrong?
UPD:
My solution:
cin >> tmp_name;
for (int i = 0, j = 0; i < size; i++, j++) {
new_hotels[j] = hotels[i];
if (hotels[i]->get_name() == tmp_name) {
new_hotels[j+1]->fillHotel();
++j;
system("clear");
}
}
hotels[size] = new Hotel();
++size;
for (int i = 0; i < size; i++) {
hotels[i] = new_hotels[i];
}
I can see different errors in your code.
For example:
Hotel *hotels[size];
size should be a constant expression and something let me think this is not the case. VLA are not part of the C++ standard. In short you cannot allocate dynamic memory on the stack. The proper initialization should be:
Hotel* hotels = new Hotel*[size];
The line in the loop:
hotels[size] = new Hotel();
you're actually accessing out of bounds of your array: size index is some memory is not included in your array and this will produce an undefined behaviour.
Another strange line is the following:
size += 1;
Despite the fact that confirms size is not a constant, you cannot increase your size of vector simply changing that variable. You're actually just changing a variable size, but the allocated memory for your array will be the same.
How resolve?
In order in increase (or change) the size of an array, the solution is almost always to create a new array, copy the old one. In your case that solution is pretty reasonable because you should copy just pointers and not entire objects.
There are a lots of question on S.O. where this topic is, for example here.
Despite of that, I strongly suggest you to use the most practical alternative, that is to use a real C++ code.
The most efficient class is std::vector which is a C++ way to handle dynamic array.
Finally, you should also consider the std::unique_ptr<T> class to handle dynamic memory and pointers.
The final solution will be a class:
std::vector<std::unique_ptr<Hotel>> hotels;
I've searched through many topics here, but they didn't seem to answer me exactly.
I'm trying to do some dynamic reallocation od arrays in C++. I can't use anything from STL libraries as I need to use this in homework where STL (vectors,...) is explicitly forbidden.
So far, I've tried to elaborate with code like this:
int * items = new int[3]; //my original array I'm about to resize
int * temp = new int[10];
for (int i = 0; i < 3; i++) temp[i] = items[i];
delete [] items; //is this necessary to delete?
items = new int [10];
for (int i = 0; i < 10; i++) items[i] = temp[i];
delete [] temp;
This seem to work, but what bothers me is the excessive number of iterations. Can't this be done anyhow smarter? Obviously, I'm working with much larger arrays than this. Unfortunately, I have to work with arrays though.
edit: When I try to do items = temp; instead of
for (int i = 0; i < 10; i++) items[i] = temp[i]; and try to std::cout all my elements, I end up with losing first two elements, but valgrind prints them correctly.
Yes, the first delete[] is necessary. Without it, you'd be leaking memory.
As to the code that comes after that first delete[], all of it can be replaced with:
items = temp;
This would make items point to the ten-element array you've just populated:
int * items = new int[3]; //my original array I'm about to resize
int * temp = new int[10];
for (int i = 0; i < 3; i++) temp[i] = items[i];
delete [] items; //delete the original array before overwriting the pointer
items = temp;
Finally, don't forget to delete[] items; when you are done with the array.
The containers of the STL were made to ease work like this. It is tedious, but there is not much of a choice, when you need to use C-arrays.
The deletion of
delete [] items;
is necessary, as when you abandon the reference to the array, which you would do with assigning a new reference in
items = new int [10];
will cause a memory leak, so this is necessary.
I have a Deck object (deck of cards) which is a double-ended queue implemented as a doubly-linked list. I would like to be able to shuffle the queue at will, but the way I would go about it is beyond me. So instead I've opted to pre-shuffle an array a pointers to the cards and enqueue them after the fact. Problem is, the code I have now doesn't seem to be initializing the pointers at all.
void BuildDeck(Deck* deck) {
Card** cards = new Card*[20];
const size_t MAX_INTEGER_LENGTH = sizeof(int) * 4;
char szPostfix[] = "_Card.bmp";
for(int i = 1; i < 21; i++) {
char path[MAX_INTEGER_LENGTH + sizeof(szPostfix) + 1];
sprintf(path,"%d%s",i, szPostfix);
cards[i-1] = new Card(i,path);
}
ShuffleArray(cards);
for (int i = 0; i < 20; i++) {
deck->PushTop(cards[i]);
}
}
void Swap(Card* a, Card* b) {
Card temp = *a;
*a = *b;
*b = temp;
}
void ShuffleArray(Card** cardArray) {
srand(dbTimer());
for (int i = 0; i < 20; i++)
Swap(cardArray[i],cardArray[rand()%20]);
}
I think where I screwed up is in the card[i] = new Card(...) line, but it somehow looks right to me.
Any suggestions would be appreciated.
DISCLAIMER: I know I should be using the standard library for most of this stuff, but I'm trying to teach myself the hard stuff first. It's just the way I learn.
EDIT: I fixed the index problem. Now I've just gotta figure out why some image aren't drawing now... :/ Thanks for the help!
Your code has many problems
You are looping with 1 <= i <= 20 but for an array of 20 elements indexing goes from 0 <= index <= 19. You need to use cards[i-1] = new Card(i,path);
You are allocating the array of pointers cards but you are not deallocating it (memory leak). Either deallocate it with delete[] cards; once you are done or just use a stack based array with Card *cards[20]; instead of allocating it with new.
The way you compute MAX_INTEGER_LENGTH shows you don't really understand what sizeof does.
This is the reason for which the cards don't get shuffled. You wrote a function that swaps two pointers, but the pointers it is swapping are local variables (parameters) of the function, not the elements of the array. One solution is to pass the parameters as pointer references by declaring swap with void Swap(Card *& a, Card *& b), another solution would be passing pointers to pointers (but this would require a more complex syntax of the implementation because of the double indirection and would also require a change in the way you call the function).
In the first for loop your starting index is 0, while in the second for loop the starting index is 0. That could be the problem.
Your code:
for(int i = 1; i < 21; i++) {
char path[MAX_INTEGER_LENGTH + sizeof(szPostfix) + 1];
sprintf(path,"%d%s",i, szPostfix);
cards[i] = new Card(i,path);
}
Here the loop should start from 0 to 20 as:
for(int i = 1 ; i < 21; i++) //incorrect - original code
for(int i = 0 ; i < 20; i++) //correct - fix
And after the fix, you could use i+1 instead of i in :
sprintf(path,"%d%s",i+1, szPostfix);
cards[i] = new Card(i+1,path);
if that is required.
I had some code thrown at me to 'productionize.' I ran a memory leak checker and it calls out the following line within the 'for' loop below as a memory leak.
someStruct->arrayMap = new std::list<BasisIndex>*[someStruct->mapSizeX];
for(int i=0; i<someStruct->mapSizeX; i++){
someStruct->arrayMap[i] = new std::list<BasisIndex>[someStruct->mapSizeY];
}
Here is how the array map is declared:
struct SomeStruct{
int mapSizeX;
int mapSizeY;
std::list<BasisIndex>** arrayMap;
};
Here are a couple usages of it:
someStruct->arrayMap[xVal][yVal].push_back(tempIndex);
for(it = someStruct->arrayMap[xVal][yVal].begin(); it != someStruct->arrayMap[xVal][yVal].end(); it++){
...
}
The memory leak checker dumped for 5 minutes before I killed it. Then I added the following bit of code in a cleanup routine but it still dumps out 150 warnings all pointing to the line of code within the for loop at the top.
for(int x=0; x<someStruct->mapSizeX; x++){
for(int y=0; y<someStruct->mapSizeY; y++){
someStruct->arrayMap[x][y].clear();
someStruct->arrayMap[x][y].~list();
}
}
std::list<BasisIndex> ** temp = someStruct->arrayMap;
delete temp;
How do I completely delete the memory associated with this array map?
Deallocate the objects in the reverse order that you allocated them.
Allocation:
someStruct->arrayMap = new std::list<BasisIndex>*[someStruct->mapSizeX];
for(int i=0; i<someStruct->mapSizeX; i++){
someStruct->arrayMap[i] = new std::list<BasisIndex>[someStruct->mapSizeY];
}
Deallocation:
for (int i=0; i<someStruct->mapSizeX; i++){
delete[] someStruct->arrayMap[i];
}
delete[] someStruct->arrayMap;
someStruct->arrayMap[x][y].~list(); <-- You should not call the destructor manually. (I didn't even know it was valid to do it that way when placement new wasn't used first...) You need to use delete instead.