Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: sf::Texture::~Texture() Crashes App On Exit  (Read 2090 times)

0 Members and 3 Guests are viewing this topic.

SlimShady

  • Newbie
  • *
  • Posts: 2
    • View Profile
sf::Texture::~Texture() Crashes App On Exit
« on: November 15, 2016, 02:05:49 pm »
Hello peeps,

I've been using SFML for quite some time now, and I have to say that I absolutely love it.

Currently I'm building a game engine + all sorts of tools for my future games, and I just threw together this little file downloader that can be used in combination with SFML resources' loadFromMemory() function.

It all works fine, the image is displayed correctly, but when I close the application, it crashes with an EXC_BAD_ACCESS error and shows me the assemly code for the destructor of the Texture and for some releasePool() method. I cannot seem to figure out why this is happening. It works without any problems with sf::Font and sf::SoundBuffer. Please help.

Download.cpp
(click to show/hide)

main.cpp
(click to show/hide)

If I replace sf::Texture and sf::Sprite with sf::Font and sf::Text respectively (and change the URL obviously), there is no problem at all.
« Last Edit: November 15, 2016, 04:36:12 pm by SlimShady »

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: sf::Texture::~Texture() Crashes App On Exit
« Reply #1 on: November 15, 2016, 03:05:10 pm »
Do you still have this problem if you don't use a separate thread?

Although the order that this code is executed is not very clear, it does look like you pass a lambda function to download and that function gets called when download.run() has finished, which is in a separate thread. This function, which is in a separate thread, accesses texture while the main thread is constantly accessing sprite, which uses texture. Since you don't have any form of security against these data-races, I would say that unpredictable behaviour should be expected :P

Even if this isn't the cause of the error, your use of threads is rather dangerous.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

SlimShady

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: sf::Texture::~Texture() Crashes App On Exit
« Reply #2 on: November 15, 2016, 04:30:48 pm »
Even if this isn't the cause of the error, your use of threads is rather dangerous.

Thanks for the quick reply. :) I've felt it was error prone, but now you confirmed it, haha. Thanks for the explanation.

I managed to apply a quick-fix by eliminating the callback and querying the state every frame, like this:

Code: [Select]
if (download.isComplete()) {
    std::string data = download.getData();
    texture.loadFromMemory(data.c_str(), data.length());
    sprite.setTexture(texture);
}

But it's not what I wanted originally. So I guess my question changes to: How do I achieve this using a callback function? Do you have any suggestions on how to improve the code?

korczurekk

  • Full Member
  • ***
  • Posts: 150
    • View Profile
    • Email
Re: sf::Texture::~Texture() Crashes App On Exit
« Reply #3 on: November 15, 2016, 07:09:17 pm »
Your first solution doesn't appear to be well-defined (you modify sf::Texture from Download::run method, which is in another thread), are sf::Texture and sf::Sprite thread-safe?

Herb

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: sf::Texture::~Texture() Crashes App On Exit
« Reply #4 on: November 17, 2016, 12:00:18 am »
Some code to help with how to use callbacks in a thread-safe manner:

typedef std::function<void(const std::string &data, bool success)> DownloadCallback;

struct DownloadItem {
    std::string data;
    DownloadCallback callback;
    bool success;
};

class Downloader {
public:
    void downloadItem(const std::string &itemUrl, const DownloadCallback &itemCallback) {
        _mutex.lock();
        // save itemUrl and itemCallback
        _mutex.unlock();
        // items get processed in background thread
    }

    void update() {
        DownloadItem item;
        bool gotItem = false;

        _mutex.lock();
        if (!_completedList.empty()) {
            item = _completedList[0];
            gotItem = true;
            _completedList.erase(_completedList.begin());
        }
        _mutex.unlock();

        if (gotItem) {
            item.callback(item.data, item.success);
        }
    }
private:
    // could use a queue instead of vector
    std::vector<DownloadItem> _completedList;
    std::mutex _mutex;
};

// UI thread
MyApp::run() {

    downloader.downloadItem("http://mysite.com/image.png", [&](const std::string &data, bool success) {
       
        if (success) {
            texture.loadFromMemory(data.c_str(), data.size());
        } else {
            sf::err() << "Failed to download image.\n";
        }
    });

    while (window.isOpen()) {

        // poll the downloader for completions
        downloader.update();

        // draw stuff
    }
}
 
« Last Edit: November 17, 2016, 12:26:54 am by Herb »