libsaria: Resizing a vector invalidates pointers

I was keeping a vector of objects, and then pass pointers to these
objects around everywhere.  HOWEVER, when vectors are resized they
allocate new memory and copy things over invalidating iterators and
pointers to the original objects.  This can cause memory corruption
issues when I try to use a pointer to an object that no longer exists.

The simple solution?  Allocate tracks dynamically and then store the
pointer in the library path.

Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This commit is contained in:
Bryan Schumaker 2012-11-24 16:50:53 -05:00 committed by Anna Schumaker
parent c094f9791f
commit 05bbad5444
6 changed files with 31 additions and 23 deletions

View File

@ -19,10 +19,11 @@ namespace libsaria
bool visible;
unsigned int id;
string path;
vector<Track> tracks;
vector<Track *> tracks;
};
void init();
void quit();
void add_path(string);
void delete_path(Path *);
void update_path(Path *);

View File

@ -66,7 +66,7 @@ static void do_task(IdleTask *task)
static void queue_task(IdleTask *task)
{
idle_queue.push_front(task);
idle_queue.push_back(task);
queued += 1.0;
libsaria::notify(IDLE_ADD, NULL);
}

View File

@ -28,7 +28,6 @@ static string id_to_filename(unsigned int id)
static void do_save_path(ofstream &stream, void *data)
{
libsaria::library::Path *path = (libsaria::library::Path *)data;
list<libsaria::Track>::iterator it;
println("Saving library path: %d", path->id);
stream << LIBRARY_CURRENT_VERSION << "\n";
@ -37,7 +36,7 @@ static void do_save_path(ofstream &stream, void *data)
stream << path->tracks.size() << "\n";
for (unsigned int i = 0; i < path->tracks.size(); i++)
path->tracks[i].save(&stream);
path->tracks[i]->save(&stream);
}
void libsaria::library::save_path(libsaria::library::Path *path)
@ -76,8 +75,8 @@ void read_path(ifstream &stream)
path_ptr = push_path(path);
for (unsigned int i = 0; i < size; i++) {
path_ptr->tracks.push_back(libsaria::Track(stream, path_ptr, version));
track = &path_ptr->tracks.back();
track = new libsaria::Track(stream, path_ptr, version);
path_ptr->tracks.push_back(track);
if ((*track)[TRACK_ID] != i)
(*track)[TRACK_ID] = i;
}

View File

@ -29,12 +29,12 @@ libsaria::library::Path *push_path(libsaria::library::Path &path)
return ptr;
}
static void hide_track(libsaria::Track &track)
static void hide_track(libsaria::Track *track)
{
if (track[TRACK_BANNED])
libsaria::ban::get_banned_plist()->remove_track(&track);
if ((*track)[TRACK_BANNED])
libsaria::ban::get_banned_plist()->remove_track(track);
else
lib_playlist.remove_track(&track);
lib_playlist.remove_track(track);
}
void pop_path(libsaria::library::Path *path)
@ -74,13 +74,10 @@ namespace libsaria
void library::delete_path(Path *path)
{
list<Track>::iterator it;
list<Path>::iterator p_it;
remove_file(path);
for (unsigned int i = 0; i < path->tracks.size(); i++) {
hide_track(path->tracks[i]);
libsaria::deck::track_removed(&path->tracks[i]);
libsaria::deck::track_removed(path->tracks[i]);
}
pop_path(path);
}
@ -101,7 +98,7 @@ namespace libsaria
{
for (unsigned int i = 0; i < path->tracks.size(); i++) {
hide_track(path->tracks[i]);
libsaria::deck::track_removed(&path->tracks[i]);
libsaria::deck::track_removed(path->tracks[i]);
}
path->visible = false;
save_path(path);
@ -114,7 +111,7 @@ namespace libsaria
Track *track;
for (unsigned int i = 0; i < path->tracks.size(); i++) {
track = &path->tracks[i];
track = path->tracks[i];
if ((*track)[TRACK_BANNED])
ban.push_back(track);
else
@ -134,7 +131,7 @@ namespace libsaria
return NULL;
if (trackid >= path_list[libid].tracks.size())
return NULL;
return &path_list[libid].tracks[trackid];
return path_list[libid].tracks[trackid];
}
void library::set_random(bool random)
@ -158,4 +155,14 @@ namespace libsaria
idle::schedule(restore_current);
}
void library::quit()
{
struct libsaria::library::Path *path;
for (unsigned int i = 0; i < path_list.size(); i++) {
path = &path_list[i];
for (unsigned int j = 0; j < path->tracks.size(); j++)
delete path->tracks[j];
}
}
}; /* namespace: libsaria */

View File

@ -18,7 +18,7 @@ static void validate_path(void *d)
path = (struct libsaria::library::Path *)d;
while (i < path->tracks.size()) {
track = &path->tracks[i];
track = path->tracks[i];
if (!libsaria::exists((*track)[TRACK_FILEPATH])) {
println("Reaping: " + (*track)[TRACK_FILEPATH]);
lib_playlist.remove_track(track);
@ -54,7 +54,7 @@ static void setup_scan_data(struct ScanData *scan, list<string> &files)
static bool find_file(libsaria::library::Path *path, string &file)
{
for (unsigned int i = 0; i < path->tracks.size(); i++) {
if (path->tracks[i][TRACK_FILEPATH] == file)
if ((*path->tracks[i])[TRACK_FILEPATH] == file)
return true;
}
return false;
@ -65,6 +65,7 @@ static void scan_path(void *data)
struct ScanData *scan = (struct ScanData *)data;
list<string>::iterator it;
libsaria::library::Path *path = scan->path;
libsaria::Track *track;
for (it = scan->files.begin(); it != scan->files.end(); it++) {
/*
@ -77,8 +78,9 @@ static void scan_path(void *data)
continue;
try {
path->tracks.push_back(libsaria::Track(*it, path));
lib_playlist.push_back(&path->tracks.back());
track = new libsaria::Track(*it, path);
path->tracks.push_back(track);
lib_playlist.push_back(track);
} catch (string message) {
println(message);
}
@ -88,12 +90,10 @@ static void scan_path(void *data)
delete scan;
}
static void update_path(void *d)
{
struct libsaria::library::Path *path;
list<string> file_list;
list<string>::iterator it;
unsigned int i;
struct ScanData *data;

View File

@ -39,6 +39,7 @@ namespace libsaria
{
println("Quitting libsaria");
app::close_pipe();
library::quit();
audio::quit();
print_format_stats();
}