2

I have an issue were a program of mine throws an access violation. Through debugging I found that for some reason the comparator-function is null. However I am not sure on why that is or how to fix it.

I created a minimum working example to reproduce the issue:

#include "Tryout.h"
#include <queue>

struct Event {
    uint64_t mv_timeout;
};

bool CompareEvents(const Event& a, const Event& b) {
    return a.mv_timeout < b.mv_timeout;
}

int main() {
    std::priority_queue<Event, std::vector<Event>, decltype(&CompareEvents)> mt_eventQueue;
    Event lo_event1{
        .mv_timeout = 1,
    };
    Event lo_event2{
        .mv_timeout = 2,
    };
    mt_eventQueue.push(lo_event1);
    mt_eventQueue.push(lo_event2);
    return 0;
}

When executing it crashes when adding the second event.

Exception thrown at 0x0000000000000000 in Tryout.exe: 0xC0000005: Access violation executing location 0x0000000000000000.

As mentioned it seems the comparing function is null, even tough I passed it via template.
What is going wrong here?

Evg
  • 25,259
  • 5
  • 41
  • 83
user2089648
  • 1,356
  • 2
  • 17
  • 31

3 Answers3

1

You need to specify the comparison function explicitly in the constructor

std::priority_queue<Event, std::vector<Event>, decltype(&CompareEvents)> mt_eventQueue( CompareEvents );

Otherwise the default argument will be used for the comparison function that will yield a null pointer.

The used constructor has the following declaration with default arguments

explicit priority_queue(const Compare& x = Compare(), Container&& = Container());
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

The template argument for the comparator function only provides the function's type, you still need to supply an actual function matching that type to an instance of std::priority_queue (via its constructor).

If you define a less-than operator yourself, then you don't need to explicitly supply any other template arguments for std::priority_queue.

For example:

struct Event
{
    uint64_t mv_timeout;
};

bool operator<(const Event &a, const Event &b)
{
    return a.mv_timeout < b.mv_timeout;
}

int main()
{
    std::priority_queue<Event> mt_eventQueue;
    Event lo_event1{
        .mv_timeout = 1,
    };
    Event lo_event2{
        .mv_timeout = 2,
    };
    mt_eventQueue.push(lo_event1);
    mt_eventQueue.push(lo_event2);
    return 0;
}
dreamlax
  • 93,976
  • 29
  • 161
  • 209
1

As far as your comparator function is not a functor, you should pass your comparator function in the constructor of std::priority:queue.

std::priority_queue<Event, std::vector<Event>, decltype(&CompareEvents)> mt_eventQueue(CompareEvents);

If your comparator was a something like this

struct CompareEvents
{
    bool operator()(const Event& a, const Event& b) {
        return a.mv_timeout < b.mv_timeout;
    }
}

You could have created the queue without specifying the functor, as far as it would be deduced by default constructor of CompareEvents,(as stated here).

std::priority_queue<Event, std::vector<Event>, CompareEvents> mt_eventQueue; //this works
Karen Baghdasaryan
  • 2,407
  • 6
  • 24