Я думал, что схожу с ума, но мои значения, выделенные кучей, изменяются при передаче cout <<
.Почему std :: cout меняет мои переменные?
Чтобы вообще описать мою установку, я получил кольцевой буфер, содержащий классы, которые в основном (value
, timestamp
) кортежей с (double
, double
) типа. Я пытаюсь реализовать задержку сигнала, так что значения, переданные в этот буфер, удерживаются в буфере для некоторой фиксированной задержки, прежде чем, наконец, будут испускаться. Я инициализировал размер буфера 1024 этих объектов с некоторым известным начальным условием, а затем, получив новое входное значение, я заглядываю в начало списка, чтобы узнать, больше ли разница между меткой времени и меткой нового значения, чем задержка , Если это так, я удаляю голову списка и отбрасываю его. Наконец, я возвращаю текущего руководителя списка.
Все это работает так, как я ожидал.
Если добавить простое заявление для печати (в моей основной, после запуска фильтра задержки):
std::cout << "Signal out of delay filter: (" << s.get << ", " << s.get_timestamp() << ").\n";
Однако, всё взрывается. Внезапно элементы в моем кольцевом буфере заполняются данными мусора, которые разбивают мои оценки временных меток.
Любая идея? Вот некоторые фрагменты кода, которые могут быть релевантными, я могу разместить больше по запросу.
Редактировать: Я установил точку наблюдения на первую запись в своем буфере, чтобы увидеть, где она была изменена, и она определенно находится в вызове cout <<
. Вот что GDB должен был сказать
Hardware watchpoint 2: d.buf.buffer[0]
Old value = {value = 0, timestamp = 0}
New value = {value = 4.10047448604823463e-322, timestamp = 0}
_IO_new_file_overflow (f=0x7ffff783a620 <_IO_2_1_stdout_>, ch=83) at fileops.c:857 857:
fileops.c: No such file or directory
редактировать 2: Я не уверен, как правильно прикрепить MVCE, но вот содержимое файлов. Я надеюсь, что это будет минимально достаточно, но он фиксирует проблему, поэтому это, по крайней мере, CVE. Если это слишком много, я могу попытаться сократить его дальше, но я рискую устранение ошибки, если он получает гораздо больше минимальным:
CMakeLists.txt:
# Project Definiton
cmake_minimum_required(VERSION 3.5)
project("ring_buffer_mvce")
set_property(GLOBAL PROPERTY CXX_STANDARD 14)
set_property(GLOBAL PROPERTY CXX_STANDARD_REQUIRED ON)
# Automated Unit Test Configuration
enable_testing()
add_executable(delay_test
src/signals/delay.cpp
src/test/delay_test.cpp)
add_test(delay_test delay_test)
SRC/сигналы/задержку. CPP
#include "delay.hpp"
delay::delay(double time, size_t buffer_size, signal<double> initial_condition) {
this->time = time;
buf = ring_buffer<signal<double> >(buffer_size);
for (int i = 0; i < buffer_size; i++) {
buf.push(initial_condition);
}
}
delay::~delay() {
}
signal<double> delay::apply(signal<double> s) {
// Add the current signal to the delay buffer
buf.push(s);
// Check to see if our current time has elapsed
double cur_time_delta = s.get_timestamp() - buf.peek().get_timestamp();
if (cur_time_delta >= (time - DELAY_EPSILON)) {
buf.pop();
}
return buf.peek();
}
SRC/сигналы/delay.hpp:
#ifndef __DELAY_H__
#define __DELAY_H__
#include <cstddef>
#include <limits>
#include "signal.hpp"
#include "filter.hpp"
#include "../utils.h"
#define DELAY_EPSILON 0.00001
class delay : public filter<double> {
public:
delay(double time, size_t buffer_size, signal<double> initial_condition);
~delay();
virtual signal<double> apply(const signal<double>);
private:
double time;
ring_buffer<signal<double> > buf;
};
#endif
SRC/сигналы/filter.hpp:
#ifndef __FILTER_HPP__
#define __FILTER_HPP__
#include "signal.hpp"
template <class t>
class filter {
public:
virtual signal<t> apply(const signal<t>) = 0;
};
#endif
SRC/сигналы/signal.hpp:
#ifndef __SIGNAL_HPP__
#define __SIGNAL_HPP__
#include <algorithm>
template <class t>
class signal {
public:
signal<t>(t value, double timestamp);
signal<t>();
t get();
double get_timestamp();
private:
t value;
double timestamp;
};
template <class t>
signal<t>::signal(t value, double timestamp) {
this->value = value;
this->timestamp = timestamp;
}
template <class t>
signal<t>::signal() {
timestamp = -1;
}
template <class t>
double signal<t>::get_timestamp() {
return timestamp;
}
template <class t>
t signal<t>::get() {
return value;
}
#endif
SRC/utils.h:
#ifndef __UTILS_H__
#define __UTILS_H__
#include <cstring>
template <class t>
class ring_buffer {
public:
ring_buffer(size_t buffer_size);
ring_buffer();
~ring_buffer();
void push(t data);
t peek();
t pop();
private:
t* buffer;
int data_start_idx;
int data_end_idx;
size_t size;
};
template <class t>
ring_buffer<t>::ring_buffer(size_t buffer_size) {
buffer = new t[buffer_size];
size = buffer_size;
data_start_idx = 0;
data_end_idx = 0;
}
template <class t>
ring_buffer<t>::ring_buffer() {
ring_buffer(64);
}
template <class t>
ring_buffer<t>::~ring_buffer() {
delete[] buffer;
}
template <class t>
t ring_buffer<t>::peek() {
return buffer[data_start_idx];
}
template <class t>
t ring_buffer<t>::pop() {
t data = buffer[data_start_idx];
data_start_idx = (data_start_idx + 1) % size;
return data;
}
template <class t>
void ring_buffer<t>::push(t data) {
buffer[data_end_idx] = data;
data_end_idx = (data_end_idx + 1) % size;
}
#endif
SRC/тест/delay_test.каст:
#include <iostream>
#include <stdio.h>
#include "../signals/signal.hpp"
#include "../signals/filter.hpp"
#include "../signals/delay.hpp"
int main(int argc, char **argv) {
delay d = delay(0.5, 1024, signal<double>(0, 0));
double sig = 0;
double t = 0;
signal<double> s = signal<double>(0, 0);
while (true) {
s = d.apply(signal<double>(sig, t));
std::cout << "Signal out of delay filter: (" << s.get() << ", " << s.get_timestamp() << ").\n";
sig += 1;
t += 0.1;
getchar();
}
return 0;
}
На самом деле не существует какого-либо времени, нет нити или чего-то еще. Я имитирую сигнал, поэтому все работает с дискретными временными метками. Я знаю, что это определенно изменяется ** внутри ** 'cout <<' через точку наблюдения GDB, я добавлю точное местоположение в свой пост. –
Нет ничего явно неправильного. 'cout' не будет мутировать аргументы, которые вы передаете. Возможно, ваши функции 'get' или' operator << 'имеют побочные эффекты? –
Моя функция get не должна, это всего лишь базовый 1-строчный метод доступа (отредактированный выше). Я понятия не имею, почему это было бы. Я не знаю, будет ли оператор << иметь хотя бы. –