C++ 为什么std::cout正在更改我的变量?
我以为我疯了,但是我的堆分配值在传递到C++ 为什么std::cout正在更改我的变量?,c++,io,c++14,std,stdout,C++,Io,C++14,Std,Stdout,我以为我疯了,但是我的堆分配值在传递到cout时被修改,当你得到这样奇怪的效果时,总是意味着某种内存损坏,因为内存管理错误 在valgrind下运行delay\u测试,会产生数千个错误: ==28617== Invalid write of size 8 ==28617== at 0x400EED: ring_buffer<signal<double> >::push(signal<double>) (in /tmp/sig/delay_test) ==
cout时被修改,当你得到这样奇怪的效果时,总是意味着某种内存损坏,因为内存管理错误
在valgrind下运行delay\u测试
,会产生数千个错误:
==28617== Invalid write of size 8
==28617== at 0x400EED: ring_buffer<signal<double> >::push(signal<double>) (in /tmp/sig/delay_test)
==28617== by 0x400C10: delay::delay(double, unsigned long, signal<double>) (in /tmp/sig/delay_test)
==28617== by 0x401065: main (in /tmp/sig/delay_test)
==28617== Address 0x5ab40c0 is 0 bytes inside a block of size 16,384 free'd
==28617== at 0x4C2D6FA: operator delete[](void*) (vg_replace_malloc.c:621)
==28617== by 0x400E04: ring_buffer<signal<double> >::~ring_buffer() (in /tmp/sig/delay_test)
==28617== by 0x400BDC: delay::delay(double, unsigned long, signal<double>) (in /tmp/sig/delay_test)
==28617== by 0x401065: main (in /tmp/sig/delay_test)
==28617== Block was alloc'd at
==28617== at 0x4C2C8F9: operator new[](unsigned long) (vg_replace_malloc.c:423)
==28617== by 0x400E3E: ring_buffer<signal<double> >::ring_buffer(unsigned long) (in /tmp/sig/delay_test)
==28617== by 0x400BB4: delay::delay(double, unsigned long, signal<double>) (in /tmp/sig/delay_test)
==28617== by 0x401065: main (in /tmp/sig/delay_test)
==28617==
...
...
==28617== HEAP SUMMARY:
==28617== in use at exit: 0 bytes in 0 blocks
==28617== total heap usage: 5 allocs, 5 frees, 92,160 bytes allocated
==28617==
==28617== All heap blocks were freed -- no leaks are possible
==28617==
==28617== For counts of detected and suppressed errors, rerun with: -v
==28617== ERROR SUMMARY: 2060 errors from 8 contexts (suppressed: 0 from 0)
==28617==大小为8的无效写入
==28617==0x400EED时:环形缓冲区::推送(信号)(in/tmp/sig/delay_测试)
==28617==by 0x400C10:delay::delay(双精度,无符号长,信号)(in/tmp/sig/delay_测试)
==28617==0x401065:main(in/tmp/sig/delay_测试)
==28617==地址0x5ab40c0是大小为16384 free'd的块中的0字节
==28617==at 0x4C2D6FA:运算符delete[](void*)(vg_replace_malloc.c:621)
==28617==by 0x400E04:ring\u buffer::~ring\u buffer()(在/tmp/sig/delay\u测试中)
==28617==by 0x400BDC:delay::delay(双精度,无符号长,信号)(in/tmp/sig/delay_测试)
==28617==0x401065:main(in/tmp/sig/delay_测试)
==28617==块在
==28617==at 0x4C2C8F9:运算符新[](无符号长)(vg_替换_malloc.c:423)
==28617==by 0x400E3E:ring\u buffer::ring\u buffer(无符号长)(in/tmp/sig/delay\u测试)
==28617==by 0x400BB4:delay::delay(双精度,无符号长,信号)(in/tmp/sig/delay_测试)
==28617==0x401065:main(in/tmp/sig/delay_测试)
==28617==
...
...
==28617==堆摘要:
==28617==在出口处使用:0块中的0字节
==28617==总堆使用率:5个alloc,5个free,分配92160字节
==28617==
==28617==所有堆块都已释放--不可能存在泄漏
==28617==
==28617==对于检测到的和抑制的错误计数,请使用:-v重新运行
==28617==错误摘要:来自8个上下文的2060个错误(已抑制:来自0的0)
在释放内存后,您正在从内存进行读写操作,也就是说,正在更改的内存位置不是您的变量,它们位于已释放的内存中,然后为其他内容重新分配
您的ring\u buffer
管理动态分配的内存,但没有用户定义的复制构造函数或赋值运算符。这意味着它完全坏了。实际上没有任何计时,没有线程或任何东西。我在模拟信号,所以一切都以离散的时间步长运行。我知道它肯定是在内部被修改的,但没有明显的错误cout
不会改变传递给它的参数。也许你的get
函数或操作你的代码中有很多问题-new[]后面必须跟delete[],违反规则3等等@KyleRush你知道规则3/5吗?为什么违反它会导致内存泄漏和/或UB?默认的环缓冲区的构造函数没有初始化任何东西,它会创建一个立即被销毁的匿名对象。缺少赋值运算符会导致buf=ring\u buffer(buffer\u size)之后出现未定义的行为代码>。是的,就是这样。在ring_buffer中定义了必要的复制构造函数,现在它可以正常工作了。看起来我有一些关于C++对象实例化过程的阅读。谢谢
# 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)
#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();
}
#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
#ifndef __FILTER_HPP__
#define __FILTER_HPP__
#include "signal.hpp"
template <class t>
class filter {
public:
virtual signal<t> apply(const signal<t>) = 0;
};
#endif
#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
#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
#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;
}
==28617== Invalid write of size 8
==28617== at 0x400EED: ring_buffer<signal<double> >::push(signal<double>) (in /tmp/sig/delay_test)
==28617== by 0x400C10: delay::delay(double, unsigned long, signal<double>) (in /tmp/sig/delay_test)
==28617== by 0x401065: main (in /tmp/sig/delay_test)
==28617== Address 0x5ab40c0 is 0 bytes inside a block of size 16,384 free'd
==28617== at 0x4C2D6FA: operator delete[](void*) (vg_replace_malloc.c:621)
==28617== by 0x400E04: ring_buffer<signal<double> >::~ring_buffer() (in /tmp/sig/delay_test)
==28617== by 0x400BDC: delay::delay(double, unsigned long, signal<double>) (in /tmp/sig/delay_test)
==28617== by 0x401065: main (in /tmp/sig/delay_test)
==28617== Block was alloc'd at
==28617== at 0x4C2C8F9: operator new[](unsigned long) (vg_replace_malloc.c:423)
==28617== by 0x400E3E: ring_buffer<signal<double> >::ring_buffer(unsigned long) (in /tmp/sig/delay_test)
==28617== by 0x400BB4: delay::delay(double, unsigned long, signal<double>) (in /tmp/sig/delay_test)
==28617== by 0x401065: main (in /tmp/sig/delay_test)
==28617==
...
...
==28617== HEAP SUMMARY:
==28617== in use at exit: 0 bytes in 0 blocks
==28617== total heap usage: 5 allocs, 5 frees, 92,160 bytes allocated
==28617==
==28617== All heap blocks were freed -- no leaks are possible
==28617==
==28617== For counts of detected and suppressed errors, rerun with: -v
==28617== ERROR SUMMARY: 2060 errors from 8 contexts (suppressed: 0 from 0)