Skip to content

Possible Memory Leakage: memmove() and memcpy() are C Functions and are Not Promised in C++ #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Peer KEYWORD1
pulseTriggered KEYWORD2
returnFloat KEYWORD2
returnDouble KEYWORD2
arraycopy KEYWORD2
LEFT_FRONT_WHEEL_SPEED_SENSOR LITERAL1
RIGHT_FRONT_WHEEL_SPEED_SENSOR LITERAL1
CENTER_REAR_WHEEL_SPEED_SENSOR LITERAL1
Expand Down
40 changes: 22 additions & 18 deletions src/ArrayList.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@


#include "Arduino.h"
#include "Memory.h"

template<typename E>
class ArrayList {
Expand All @@ -14,8 +15,7 @@ class ArrayList {
if (newCapacity < minCapacity)
newCapacity = minCapacity;
E *newArray = new E[newCapacity];
memmove(newArray, _array, _size * sizeof(E));
delete[] _array;
arraycopy(_array, newArray, _size);
_array = newArray;
_capacity = newCapacity;
}
Expand All @@ -24,16 +24,12 @@ class ArrayList {
grow(minCapacity);
}
void ensureCapacityInternal(size_t minCapacity) { ensureExplicitCapacity(max(10, minCapacity)); }
void add(E *elements, size_t size) {
ensureCapacityInternal(_size + size);
memcpy(_array + _size, elements, size * sizeof(E));
}

public:
explicit ArrayList(size_t initialCapacity = 10) :
_size(0), _capacity(initialCapacity), _array(new E[initialCapacity]) {}
ArrayList(E const *const initialArray, size_t size) : _size(0), _capacity(size), _array(new E[size]) {
memcpy(_array, initialArray, size * sizeof(E));
ArrayList(E const *const initialArray, size_t size) : _size(size), _capacity(size), _array(new E[size]) {
arraycopy(initialArray, _array, size);
}
ArrayList(const ArrayList<E> &other) : ArrayList(other._array, other._size) {}
~ArrayList() { delete[] _array; }
Expand All @@ -42,19 +38,18 @@ class ArrayList {
void set(int index, const E &element) { _array[index] = element; }
E get(int index) { return _array[index]; }
void clear() {
delete[] _array;
_array = new E[0];
_size = _capacity = 0;
}
void add(E const *const elements, size_t size) {
ensureCapacityInternal(_size + size);
arraycopy(elements, _array, size, 0, _size);
_size += size;
}
void add(const E &element) {
ensureCapacityInternal(_size + 1);
_array[_size++] = element;
}
ArrayList<E> add(const ArrayList<E> &other) {
ArrayList<E> result = copy();
result += other;
return result;
}
bool contains(const E &element) { return indexOf(element) >= 0; }
int indexOfInRange(const E &element, int start, int stop) {
for (int i = start; i < stop; i++)
Expand All @@ -70,13 +65,18 @@ class ArrayList {
return -1;
}
int lastIndexOf(const E &element) { return lastIndexOfInRange(element, 0, _size); }
ArrayList<E> copy() { return ArrayList<E>(reinterpret_cast<size_t>(this)); }
ArrayList<E> copy() { return ArrayList<E>(*this); }
E operator[](int index) { return get(index); }
ArrayList<E> operator+(const E &element) {
ArrayList<E> result = copy();
result += element;
return result;
}
ArrayList<E> operator+(const ArrayList<E> &other) { return add(other); }
ArrayList<E> operator+(const ArrayList<E> &other) {
ArrayList<E> result = copy();
result += other;
return result;
}
ArrayList<E> &operator+=(const E &element) {
add(element);
return *this;
Expand All @@ -88,8 +88,12 @@ class ArrayList {
ArrayList<E> &operator=(const ArrayList<E> &other) {
if (this != &other) {
ensureCapacityInternal(other._capacity);
if (other._size > 0)
memcpy(_array, other._array, _size * sizeof(E));
if (other._size > 0) {
_array = new E[other._capacity];
_capacity = other._capacity;
arraycopy(other._array, _array, other._size);
_size = other._size;
}
}
return *this;
}
Expand Down
5 changes: 2 additions & 3 deletions src/Controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,17 @@ class Controller : public Device<T> {
protected:
ArrayList<String> _device_tags;
ArrayList<Device<E>> _devices;
void _attachDevice(const String &tag, Device<E> device) {
void _attachDevice(const String &tag, const Device<E> &device) {
_device_tags.add(tag);
_devices.add(device);
device.tag(tag);
}

public:
Controller() : Device<T>() {}
int level() { return this->_parentTags.size(); }
const ArrayList<Device<E>> &devices() { return _devices; }
void device(const String &tag, const Device<E> &device) { _attachDevice(tag, device); }
Device<E> device(const String &tag) { return _devices.get(_device_tags.indexOf(tag)); }
Device<E> device(const String &tag) { return _devices[_device_tags.indexOf(tag)]; }
void initialize(const ArrayList<String> &parentTags) override {
Device<E>::initialize(parentTags);
for (Device<E> d: _devices)
Expand Down
1 change: 1 addition & 0 deletions src/Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Device {
explicit Device(const ArrayList<int> &pins) : _pins(pins) {}
Device() : Device(ArrayList<int>(0)) {}
~Device() = default;
int level() { return _parentTags.size(); }
void tag(const String &tag) { _tag = tag; }
String tag() { return _tag; }
const ArrayList<String> &parentTags() { return _parentTags; }
Expand Down
1 change: 1 addition & 0 deletions src/LEADS.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "Controller.h"
#include "Device.h"
#include "Memory.h"
#include "Peer.h"
#include "PredefinedTags.h"
#include "Utils.h"
Expand Down
12 changes: 12 additions & 0 deletions src/Memory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef MEMORY_H
#define MEMORY_H


template<typename E>
void arraycopy(const E *const from, E *to, int size, int fromOffset = 0, int toOffset = 0) {
for (int i = 0; i < size; i++)
to[i + toOffset] = from[i + fromOffset];
}


#endif // MEMORY_H
5 changes: 3 additions & 2 deletions src/Peer.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#include "Peer.h"


Peer::Peer(unsigned int baudRate, String separator, String remainder) :
// std::move() is not available in the C library
Peer::Peer(unsigned int baudRate, const String &separator, const String &remainder) : // NOLINT(*-pass-by-value)
Controller<String, String>(), _baudRate(baudRate), _separator(separator), _remainder(remainder) {}
void Peer::initialize(const ArrayList<String> &parentTags) {
Controller<String, String>::initialize(parentTags);
Serial.begin(_baudRate);
}
String Peer::read() {
char c = Serial.read();
char c = char(Serial.read());
if (c > 0) {
_remainder += c;
if (!_remainder.endsWith(_separator))
Expand Down
2 changes: 1 addition & 1 deletion src/Peer.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Peer : public Controller<String, String> {
String _separator, _remainder;

public:
explicit Peer(unsigned int baudRate = 9600, String separator = ";", String remainder = "");
explicit Peer(unsigned int baudRate = 9600, const String &separator = ";", const String &remainder = "");
void initialize(const ArrayList<String> &parentTags) override;
String read() override;
void write(String payload) override;
Expand Down
4 changes: 2 additions & 2 deletions src/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

bool pulseTriggered(int pin) { return digitalRead(pin) == LOW; }

void returnFloat(Peer peer, const String &tag, float n) { peer.write(tag + ":" + n); }
void returnFloat(Peer &peer, const String &tag, float n) { peer.write(tag + ":" + n); }

void returnDouble(Peer peer, const String &tag, double n) { peer.write(tag + ":" + n); }
void returnDouble(Peer &peer, const String &tag, double n) { peer.write(tag + ":" + n); }
4 changes: 2 additions & 2 deletions src/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

bool pulseTriggered(int pin);

void returnFloat(Peer peer, const String &tag, float n);
void returnFloat(Peer &peer, const String &tag, float n);

void returnDouble(Peer peer, const String &tag, double n);
void returnDouble(Peer &peer, const String &tag, double n);


#endif // UTILS_H
4 changes: 2 additions & 2 deletions src/VoltageSensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ VoltageSensor::VoltageSensor(float r1, float r2, const ArrayList<int> &pins) :

void VoltageSensor::initialize(const ArrayList<String> &parentTags) {
Device<float>::initialize(parentTags);
pinMode(_pins.get(0), INPUT);
pinMode(_pins[0], INPUT);
}

float VoltageSensor::read() { return (float) analogRead(_pins.get(0)) * _factor * 5 / 1023; }
float VoltageSensor::read() { return (float) analogRead(_pins[0]) * _factor * 5 / 1023; }
4 changes: 2 additions & 2 deletions src/WheelSpeedSensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ WheelSpeedSensor::WheelSpeedSensor(const ArrayList<int> &pins, OnUpdate onUpdate

void WheelSpeedSensor::initialize(const ArrayList<String> &parentTags) {
Device<float>::initialize(parentTags);
pinMode(_pins.get(0), INPUT);
pinMode(_pins[0], INPUT);
_t1 = 0;
_t2 = millis();
_consecutive = false;
Expand All @@ -15,7 +15,7 @@ void WheelSpeedSensor::initialize(const ArrayList<String> &parentTags) {
float getRPM(unsigned long t1, unsigned long t2) { return float(60000.0 / double(t2 - t1)); }

float WheelSpeedSensor::read() {
if (pulseTriggered(_pins.get(0))) {
if (pulseTriggered(_pins[0])) {
if (!_consecutive) {
_consecutive = true;
_t1 = _t2;
Expand Down
19 changes: 12 additions & 7 deletions test/ArrayList.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
#include "LEADS.h"

ArrayList<int> test = ArrayList<int>();
const int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
ArrayList<int> b = ArrayList<int>(a, 10);
const int c[] = {12, 13};
ArrayList<int> d = ArrayList<int>(c, 2);

void setup() { Serial.begin(9600); }
void setup() {
Serial.begin(9600);
b.add(11);
b = b + d;
}

void loop() {
test.add(1);
if (test.size() > 20)
test.clear();
Serial.println(test.size());
delay(100);
Serial.println(b.size());
Serial.println(b[11]);
delay(1000);
}