我目前正在尝试编程神经网络头文件以训练神经网络,NN.h文件包含所有神经网络内容。 NN.h还包括我自己编写的另一个头文件,名为Matrix.h,它包含一个用于处理内存管理所有矩阵内容的类。
当我没有为Matrix对象使用向量时,内存管理工作正常但是只要我将它们用于向量,我就会出现Segmentation fault错误。
这是程序输出:
Matrix destruction started
0 0 0
Matrix destruction started
0 0 0
Matrix destruction started
0 0 0
0 0 0
0 0 0
Matrix destruction started
2 2 2
Matrix destruction started
10 10 10
Matrix destruction started
9
Segmentation fault (core dumped)
NN.h:
#include <vector>
#include <string>
#include <stdlib.h>
#include "matrix.h"
#include <time.h>
#include <string>
class NN{
private:
std::vector<int> info;
std::vector<Matrix<double> > layer;
std::vector<Matrix<double> > weights;
std::vector<Matrix<double> > bias;
std::vector<Matrix<double> > result;
std::vector<Matrix<double> > temp;
double learnigRate;
public:
NN(std::vector<int> &layers){
info = layers;
layer.reserve(layers.size());
for (size_t i = 0;i < layers.size();i++){
layer.push_back(Matrix<double> (layers[i],1,0));
}
weights.reserve(layers.size()-1);
for (size_t i = 0;i < (layers.size()-1);i++){
weights.push_back(Matrix<double> (layers[i],layers[i+1],0));
}
bias.reserve(layer.size()-1);
for (size_t i= 0; i < (layers.size()-1);i++){
bias.push_back(Matrix<double> (layers[i+1],1,2));
}
result.push_back(Matrix<double> (layers[layers.size()-1],1,10));
temp.push_back(Matrix<double> (1,1,9));
}
~NN(){
for (size_t i = 0;i < info.size();i++){
delete &layer[i];
}
for (size_t i = 0;i < (info.size()-1);i++){
delete &weights[i];
}
for (size_t i= 0; i < (info.size()-1);i++){
delete &bias[i];
}
delete &result[0];
delete &temp[0];
}
};
Matrix.h:
#include <stdio.h>
#include <iostream>
#include <exception>
template <class W> class Matrix{
private:
int state = 0;
int printError(Matrix<W> &a){
if(state != 0 && a.state != 0){
std::cerr <<"matrix.h error : " << "Both matrices not correctly initialized!" << std::endl;
return 1;
}
if(state != 0){
std::cerr <<"matrix.h error : " << "Matrix 1 not correctly initialized!" << std::endl;
return 1;
}
if(a.state != 0){
std::cerr <<"matrix.h error : " << "Matrix 2 not correctly initialized!" << std::endl;
return 1;
}
return 0;
}
public:
W ** matrix;
int size_x,size_y;
template <typename X> Matrix(int size_tx,int size_ty,X value){
W temp = (W) value;
size_x = size_tx;
size_y = size_ty;
int x = 0;
try{
matrix = new W*[size_y];
}
catch(const std::bad_alloc&)
{
std::cerr << "Could not allocate matrix: bad_alloc()" << std::endl;
state = 1;
return;
}
try{
for(x = 0; x < size_y;x++){
matrix[x] = new W[size_x];
}
}
catch (const std::bad_alloc&)
{
std::cerr << "Could not allocate matrix: bad_alloc()" << std::endl;
for(int i = 0; i < x-1;i++){
delete [] matrix[i];
}
state = 1;
return;
}
for(int i = 0; i < size_y; i++){
for(int j = 0;j< size_x;j++){
matrix[i][j] = temp;
}
}
state = 0;
}
~Matrix(){
if (state == 0)
freeMatrix();
}
int freeMatrix(){
std::cout << "Matrix destruction started" << std::endl;
printMatrix();
for(int i = 0; i < size_y;i++){
delete [] matrix[i];
}
delete [] matrix;
return 0;
}
int printMatrix(){
for(int i = 0; i < size_y; i++){
for(int j = 0;j< size_x;j++){
std::cout << matrix[i][j] << " ";
}
printf("\n");
}
return 0;
}
};
main.cpp中:
#include <iostream>
#include <vector>
#include "matrix.h"
#include "NN.h"
using namespace std;
int main(){
vector<int> net (3);
net = {3,3};
NN n(net);
return 0;
}
这些是我的代码的缩短版本,但相关部分应该仍然存在。
删除NN类的析构函数时仍然存在相同的错误, 但是,当我删除Matrix析构函数时没有错误,但我想用一个尊重内存管理的干净解决方案解决问题。
如果您需要更多信息,请随时问我。
答案 0 :(得分:0)
显然,~NN()
实施是错误的。删除未动态分配的对象是没有意义的。添加项目时,对象(堆叠中)将被推回。
鉴于您在NN
中使用了向量,为什么不对Matrix
使用向量?它将大大简化代码,有助于防止内存泄漏并使代码更强大,更安全......
在构造函数中捕获异常并设置标志以指示失败是一个非常糟糕的主意。 事实上,语言中增加了例外以避免这种模式。如果不是更多的话,已经知道差不多20年了......
另一件事是你复制Matrix
对象而没有定义复制构造函数(也没有赋值运算符)并且假设你使用的是C ++ 11,你还应该提供移动构造函数和赋值。
您应该做的另一件事是始终将匹配的头文件放在给定源的包含列表中(仅在预编译头文件(如果适用)之后)。这样,它有助于确保任何头文件自行编译。
我建议你阅读关于C ++的好书,例如 Exceptional C ++ 。网上还有很多信息。例如,您应该学习其他5的规则(例如:http://www.cppsamples.com/common-tasks/rule-of-five.html或http://en.cppreference.com/w/cpp/language/rule_of_three)。
在现代C ++中,建议避免显式内存管理。您应该使用类似&#39; std :: vector&#39;,&#39; std :: unique_ptr ,
std :: shared_ptr`等类来帮助您编写可维护的异常安全代码,该代码可按预期工作
如果你想做C ++,那么你必须付出很多努力来学习。否则,切换到更简单的语言,如C#或Swift ......