I write a simple queue implements by array and when I test it, I faced a wired problem.
// vector_queue.h
#ifndef TEST_VECTOR_QUEUE_H
#define TEST_VECTOR_QUEUE_H
#include "linked_queue.h"
template<class T>
class vector_queue {
public:
explicit vector_queue(size_t capacity = default_capacity)
: capacity(capacity), queue(new T[capacity]), head(0), tail(0) {}
~vector_queue() {
delete[] queue;
std::cout << "~" << std::endl;
}
[[nodiscard]] bool empty() const { return head == tail; }
T dequeue() {
if (empty()) {
std::cout << "The queue is empty!" << std::endl;
return 0;
}
T ret = queue[head];
head = (head + 1) % capacity;
return ret;
}
void enqueue(const T &x) {
if (full()) {
std::cout << "The queue is full!" << std::endl;
return;
}
queue[tail] = x;
tail = (tail + 1) % capacity;
}
[[nodiscard]] bool full() const { return head == (tail + 1) % capacity; }
private:
static const size_t default_capacity;
T *queue;
size_t head, tail;
size_t capacity;
public:
vector_queue &operator+(const T &x) {
enqueue(x);
return *this;
}
T operator--() {
return this->dequeue();
}
vector_queue &operator=(const vector_queue &rhs) {
if (this != &rhs) {
this->queue = rhs.queue;
this->head = rhs.head;
this->tail = rhs.tail;
this->capacity = rhs.capacity;
}
return *this;
}
friend std::ostream &operator<<(std::ostream &os, const vector_queue &q) {
for (int i = q.head;; i = (i + 1) % q.capacity) {
if (i == q.tail)
break;
os << q.queue[i] << " ";
}
os << std::endl;
return os;
}
friend vector_queue &operator+(const T &x, vector_queue &q) {
q.enqueue(x);
return q;
}
};
template<typename T>
const size_t vector_queue<T>::default_capacity = 4;
#endif //TEST_VECTOR_QUEUE_H
#include <iostream>
#include "vector_queue.h"
using Queue = vector_queue<int>;
using std::cout;
using std::endl;
int main() {
Queue q;
--q; // Display:The queue is empty!
q = q + 5 + 6 + 3;
cout << q; // Display:5 6 3
cout << --q << endl; // Display:5
cout << q; // Display:6 3
q = 9 + q;
cout << q; // Display:6 3 9
q = 2 + q; // Display:The queue is full!
cout << q; // Display:6 3 9
return 0;
}
I use -fsanitize=leak
in my cmake configuration. After displaying all the messages, it won't stop. If I remove -fsanitize=leak
, everything will be fine, or if I delete q = q + 5 + 6 + 3;
it will be fine as well. I am quite curious about it!
I have tried lldb
and received:
* thread #2, stop reason = EXC_BAD_ACCESS (code=1, address=0x102910000)
frame #0: 0x0000000100125b4c libclang_rt.lsan_osx_dynamic.dylib`__lsan::ScanRangeForPointers(unsigned long, unsigned long, __sanitizer::InternalMmapVector<unsigned long>*, char const*, __lsan::ChunkTag) + 232
libclang_rt.lsan_osx_dynamic.dylib`__lsan::ScanRangeForPointers:
-> 0x100125b4c <+232>: ldr x26, [x22]
0x100125b50 <+236>: cmp x26, #0x4, lsl #12 ; =0x4000
0x100125b54 <+240>: b.lo 0x100125b3c ; <+216>
0x100125b58 <+244>: cbz x29, 0x100125d90 ; <+812>
my device: MacBook Pro m1, macOS 11.3, compiler: clang version 12.0.0 which installed by homebrew.