C++程序运行内存错误

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++程序运行内存错误相关的知识,希望对你有一定的参考价值。

程序抽象了一个稀疏矩阵,用一个二维数据表示(元素为0或1)非零元的位置,另一个一维数据顺序存放非零元的值,程序函数运行都没有问题,错误好像是出在SpaseMatrix的析构函数上,就是释放内存空间的语句,如果将两个delete语句删除,则可以正常运行,但这样会不会导致内存泄漏?

程序代码如下:
//SparseMatrix.h
#ifndef SPARSEMATRIX_H
#define SPARSEMATRIX_H

class SparseMatrix

public:

SparseMatrix(int r, int c, int num);

~SparseMatrix();

void setBits(int rMulc);

void setA(int x, int value);

SparseMatrix* AddMatrix(SparseMatrix b);

int getN();

int getM();

int getNums();

int* getBits();

int* getA();
private:
int n,m;//记录m*n阶矩阵的维数

int nums;//记录矩阵中非零元的个数,即一维数组的维数

int* bits;

int* a;

;

#endif

//SparseMatrix.cpp
#include "SparseMatrix.h"

SparseMatrix::SparseMatrix(int r, int c, int num):m(r), n(c), nums(num)

bits = new int[m*n];

for (int i=0; i<m*n; i++)

*(bits + i) = 0;


a = new int[nums];

for (int j=0; j<nums; j++)

*(a + j) = 0;



SparseMatrix::~SparseMatrix()

// delete[] bits;

// delete[] a;


void SparseMatrix::setBits(int rMulc)

*(bits + rMulc) = 1;


void SparseMatrix::setA(int x, int value)

*(a+x) = value;


SparseMatrix* SparseMatrix::AddMatrix(SparseMatrix b)

SparseMatrix* sum = new SparseMatrix(m, n, nums + b.getNums());

int j = 0;//记录和矩阵的非零元次序

int k = 0;//记录被加矩阵非零元的次序

int l = 0;//记录参数矩阵非零元的次序

for (int i=0; i<m*n; i++)

if ((*(bits+i) == 0) && ((*(b.getBits()+i)) == 0))

continue;

else if ((*(bits+i) == 0) && ((*(b.getBits()+i)) == 1))

sum->setBits(i);

sum->setA(j, *(b.getA()+l));

j++;

l++;

else if ((*(bits+i) == 1) && ((*(b.getBits()+i)) == 0))

sum->setBits(i);

sum->setA(j, *(a + k));

j++;

k++;

else if((*(bits+i) == 1) && ((*(b.getBits()+i)) == 1))

sum->setBits(i);

sum->setA(j, (*(a + k)) + *(b.getA() + l));

j++;

k++;

l++;



return sum;


int* SparseMatrix::getBits()

return bits;


int* SparseMatrix::getA()

return a;


int SparseMatrix::getM()

return m;


int SparseMatrix::getN()

return n;


int SparseMatrix::getNums()

return nums;


字数超了,我打在补充里面~
//main.cpp
#include<iostream>
using namespace std;
#include"SparseMatrix.h"

void main()

int m, n, value;
int num;
cout << "输入矩阵的维数(行 列):"<< endl;
cin >> m >> n;
cout << "输入非零元个数:" << endl;

cin >> value;

SparseMatrix a(n, m, value);

int r,c;
for (int i=0; i< value; i++)

cout << "输入第" << (i+1) << "个非零元的行列值" << endl;
cin >> r >> c;
cout << "输入这个元素的值:" << endl;
cin >> num;
a.setBits(r*n+c);
a.setA(i,num);

cout << "第二个矩阵:" << endl;
cout << "输入矩阵的维数(行 列):"<< endl;
cin >> m >> n;
cout << "输入非零元个数:" << endl;
cin >> value;
SparseMatrix b(m, n, value);
for (int i=0; i< value; i++)

cout << "输入第" << (i+1) << "个非零元的行列值" << endl;
cin >> r >> c;
cout << "输入这个元素的值:" << endl;
cin >> num;
b.setBits(r * n + c);
b.setA(i,num);

SparseMatrix* sum = a.AddMatrix(b);


字数不够,不能打输出了,但错误和输出没什么关系,请帮我看下,谢谢了~

问题出在你没有自己写拷贝构造函数,这对于类成员有指针的情况是非常危险的。因为如果你不自己写的话,编译器会为你调用默认的拷贝构造函数,而默认拷贝构造函数是简单的位拷贝,所以指针会被直接拷贝过去,而不是另外开辟一个内存。
对于你的程序,这个问题体现在SparseMatrix* sum = a.AddMatrix(b);这句话上,你看着简单的把b作为参数传了进去,但是因为你采用的是值传递,所以,编译器会在AddMatrix函数体内为你生成一个b的拷贝,这是调用了拷贝构造函数,而你是采用默认拷贝构造函数,所以这个拷贝的成员bits和a这两个数组的指针实际上和b的是一样的,在函数执行完以后,编译器会释放掉这个临时的拷贝,调用了析构函数,删掉了bits和a,注意,这时b的成员bits和a也被删掉了。而在main函数结束时,b和a都要被释放掉,所以当b执行析构的时候就会再次删除原本已经delete掉的bits和a数组,所以导致了错误。
建议改正的地方:
1>如果有指针成员的话一定要自己写拷贝构造函数。
2>函数传值如果传的是自定义类型,而且你不会对这个值在函数内做改变,那么建议传入const 引用类型,这样可以省掉生成临时拷贝的步骤。
3>写程序时,变量名要有意义,不要全都是a,b之类的。。。调试起来都麻烦。。。

对于你这个程序,简单的修改方案如下:
在类内加入这个拷贝构造函数
SparseMatrix(const SparseMatrix& sm)

n = sm.n;
m = sm.m;
nums = sm.nums;
bits = new int[nums];
a = new int[n*m];
参考技术A 我是vc6.0写的大家帮我看下为什么一运行就出现内存错误,这个程序我是想看你定义的结构体指针没有分配空间,不能进行赋值操作。你可以用动态分配,也

C++ 内存分段错误?

【中文标题】C++ 内存分段错误?【英文标题】:C++ Memory Segmentation Fault? 【发布时间】:2016-03-21 09:13:50 【问题描述】:

我编写了一个程序,该程序从谷歌金融获取股票数据并执行买入/卖出决策。我在 Visual Studio C++ 中编写了它,它在 Windows 上运行良好,但是当我尝试在 ubautu 上使用 g++ -std=c++11 stock.cpp 编译它并运行 a.out 时,我遇到了 seg 错误。我哪里错了?

从 main(),第二次调用 SMA() 时出错:

            decisionPoint_model_call(); 
            //this function call a function called SMA() twice to calculate two different moving averages
            //the second time SMA() is called from inside decisionPoint_model_call() a seg. fault occurs

gdb 给了我以下错误:

0xb7f42ac5 in std::basic_ostream >& std::operator(std::basic_ostream >&, std::basic_string, std::allocator > const&) () 来自 /usr/lib /i386-linux-gnu/libstdc++.so.6

代码如下:

stock.cpp

#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <vector>
#include <deque>


using namespace std;

int numberOfDays; //total number of days
int dayNumber = 0; //0 being the starting date

struct each_day 
    string date;
    float open;
    float high;
    float low;
    float close;
    float volume;
    float mov_avg[1];

;

each_day *day = nullptr;

//store parced cotents in structure one day at a time
void float2structure(string date, float open, float high, float low, float close, float volume)

    if (dayNumber == 0)
    
        day = new each_day[numberOfDays];
    

    day[dayNumber].date = date;
    day[dayNumber].open = open;
    day[dayNumber].high = high;
    day[dayNumber].low = low;
    day[dayNumber].close = close;
    day[dayNumber].volume = volume;

    if (dayNumber != numberOfDays)
    
        dayNumber++;
    





void line2float(string line_string) //reads line and converts appropriate type


    string date;
    float open;
    float high;
    float low;
    float close;
    float volume;

    string temp;

    int dataBlocks = 1;

    istringstream ss(line_string);
    while (!ss.eof())
    
        switch (dataBlocks)
        
        case 1:
            getline(ss, date, ',');
        case 2:
            getline(ss, temp, ',');
            if (temp == "-") 
                temp = "0";
            
            open = stof(temp);
        case 3:
            getline(ss, temp, ',');
            if (temp == "-") 
                temp = "0";
            
            high = stof(temp);
        case 4:
            getline(ss, temp, ',');
            if (temp == "-") 
                temp = "0";
            
            low = stof(temp);
        case 5:
            getline(ss, temp, ',');
            if (temp == "-") 
                temp = "0";
            
            close = stof(temp);
        case 6:
            getline(ss, temp, ',');
            if (temp == "-") 
                temp = "0";
            
            volume = stof(temp);
        

    
    float2structure(date, open, high, low, close, volume);


//gets line, sort in correct order, send each line to next function 
void lineGet(ifstream &inFile) 

    cout << "Reorganizing data... be patient..." << endl;

    vector<string> lines_in_reverse;
    string line;
    while (getline(inFile, line))
    
        // Store the lines in reverse order.
        lines_in_reverse.insert(lines_in_reverse.begin(), line);

    

    numberOfDays = lines_in_reverse.size() - 1;  

    for (int x = 0; x < numberOfDays; x++)
    
        line2float(lines_in_reverse[x]);
    




//calculed the SMA and stores that in data.mov_avg[x]
void SMA(int movingAvg, int mv_num)

    deque <float> sma;
    float smaSize = (float)movingAvg;

    float sum_of_elems = 0;

    for (dayNumber = 0; dayNumber < numberOfDays; dayNumber++)
    
        cout << day[dayNumber].date << " " <<dayNumber<<endl;

        if (dayNumber <= smaSize - 1)
        

            sma.push_front(day[dayNumber].close);

            day[dayNumber].mov_avg[mv_num] = 0; //ERROR HERE?


            if (dayNumber == smaSize - 1)
            
                for (float n : sma) 
                    sum_of_elems += n;
                

                day[dayNumber].mov_avg[mv_num] = sum_of_elems / smaSize;

            


        
        else
        
            sum_of_elems = 0;
            sma.pop_back();
            sma.push_front(day[dayNumber].close);

            for (float n : sma)
            
                sum_of_elems += n;
            

            day[dayNumber].mov_avg[mv_num] = sum_of_elems / smaSize;

        

    



//function to analyze data and report trades
void decisionPoint_model(string startDate)

    dayNumber = 0;
    bool holdingLong = false;
    bool shortSell = false;
    float totalProfit = 0;
    float buyPrice;
    float sellPrice;
    float shortPrice;
    float coverPrice;

    //loop though each day, compare moving averages, buy and sell based on moving averages
    for (; dayNumber < numberOfDays; dayNumber++) 
        //cout << day[dayNumber].moving_avg[0] << " " << day[dayNumber].moving_avg[1] << endl;
        if (day[dayNumber].mov_avg[1] != 0) 

            if (day[dayNumber].mov_avg[0] < day[dayNumber].mov_avg[1] && holdingLong == true) 
                //sell
                sellPrice = day[dayNumber + 1].open;
                totalProfit += (sellPrice - buyPrice);
                cout << "Sell: $" << day[dayNumber + 1].open << " on " << day[dayNumber + 1].date << endl;
                cout << "Profit from trade: $" << sellPrice - buyPrice << endl;
                cout << "Total profit: $" << totalProfit << endl;
                cout << endl;
                holdingLong = false;
            
            if (day[dayNumber].mov_avg[0] < day[dayNumber].mov_avg[1] && shortSell == false) 
                //short
                shortPrice = day[dayNumber + 1].open;
                cout << "Short: $" << day[dayNumber + 1].open << " on " << day[dayNumber + 1].date << ", ";
                shortSell = true;
            
            if (day[dayNumber].mov_avg[0] > day[dayNumber].mov_avg[1] && shortSell == true) 
                //cover
                coverPrice = day[dayNumber + 1].open;
                totalProfit += (shortPrice - coverPrice);
                cout << "Cover: $" << day[dayNumber + 1].open << " on " << day[dayNumber + 1].date << endl;
                cout << "Profit from trade: $" << shortPrice - coverPrice << endl;
                cout << "Total profit: $" << totalProfit << endl;
                cout << endl;
                shortSell = false;
            
            if (day[dayNumber].mov_avg[0] > day[dayNumber].mov_avg[1] && holdingLong == false) 
                //buy
                buyPrice = day[dayNumber + 1].open;
                cout << "Buy: $" << day[dayNumber + 1].open << " on " << day[dayNumber + 1].date << ", ";
                holdingLong = true;
            
        

    
    cout << endl;
    cout << "Total profits from strategy: $" << totalProfit << endl;
    cout << endl;



void decisionPoint_model_call() 


    cout << "testing end" << endl;
    cout << "\nWe are going to perfrom a decision point analysis." << endl;
    cout << "This requires two moving averages relatively close by (eg. 10 and 15 day moving averages)." << endl;
    cout << endl;
    int movingavg;
    cout << "Set the first moving average (ex. 10):";
    cin >> movingavg;
    SMA(movingavg, 0);

    cout << endl;
    cout << "Set the second moving average (ex. 15):";
    cin >> movingavg;
    SMA(movingavg, 1); //ERROR OCCURS THE SECOND TIME WE CALL SMA() 



    cout << "\nData stretches from: " << day[0].date << " to " << day[numberOfDays - 1].date << endl;
    cout << "NO ERROR" << endl;
    string startDate;
    cout << "Enter a date to begin analysis: ";
    cin >> startDate;
    cout << endl;

    decisionPoint_model(startDate);
    cout << "Open price on first day (given data): $" << day[0].open << endl;
    cout << "Close price on last day (given data): $" << day[numberOfDays - 1].close << endl;
    cout << "For a total price change of: $" << day[numberOfDays - 1].close - day[0].open << endl;
    cout << endl;


void file_get() 


functionStart:
    string filename;
    cout << "\nEnter file name (ex. goog.csv):";
    cin >> filename;

    ifstream inFile(filename.c_str());
    if (inFile.is_open()) 
        cout << "\nLoading file...\n" << endl;
        lineGet(inFile);
        inFile.close();
    
    else 
        cout << "No file was found on disk, retrieving one from the web..." << endl;
        system("python stockFetch.py");
        goto functionStart;
    




int main()


    cout << endl;
    cout << "What type on analysis would you like to perform?" << endl;
    cout << "1. Decision Point Analysis - based on historical data." << endl;
    cout << endl;
    cout << "Enter number: "; //only number that works is 1 currently
    int analysisNumber;
    cin >> analysisNumber;

    switch (analysisNumber) 
    case 1:
        file_get(); 
            //order of calls: 1.file_get() -> 2.lineGet() -> 3.line2float() -> 4.float2structure()
            //function 2 - 4 are called over and over again to store each line from the cvs file to the structure

        decisionPoint_model_call(); 
            //this function call function called SMA() twice to calculate two different moving averages
            //the second time SMA() is called from inside decisionPoint_model_call() a seg. fault occurs



    

    system("pause");
    return 0;

要获取股票数据文件,您需要从here获取csv文件并将其保存为aapl.csv

或者保存以下 python 文件,因为如果 c++ 程序在磁盘上找不到 .csv 文件,它会调用它。

stockFetch.py​​

import sys, os, urllib

#get the csv file from google finance
tickerSymbol= raw_input('Enter the ticker symbol: ')
startDate = raw_input('Enter the start date(Ex. Jan 20, 2015): ')
endDate = raw_input('Enter the end date: ')
startDate.replace (" ", "+")
startDate.replace (",", "2C")
endDate.replace (" ", "+")
endDate.replace (",", "2C")

url = "http://www.google.com/finance/historical?q="+str(tickerSymbol)+"&startdate="+str(startDate)+"&enddate="+str(endDate)+"&output=csv"


urllib.urlretrieve(url, str(tickerSymbol))
if os.path.isfile(str(tickerSymbol)):
       os.rename(str(tickerSymbol), str(tickerSymbol)+".csv")
       print ("--File Fetched--")
       sys.exit()

print ("--Could not find file--")

【问题讨论】:

请发帖minimal reproducible example。关键字 - 最小。 或者使用调试器。您至少需要使用基本的调试技能来查找崩溃发生的位置,然后在您不明白为什么时提出问题。您可能正在对向量和字符串的大小做出假设,或者做一些坏事,例如从零的无符号值中减去 1。 【参考方案1】:

我不知道这是否是唯一的错误,但确实是一个错误。

您定义大小为 1 的 each_day::mov_avg

float mov_avg[1];

但在位置2使用

day[dayNumber].mov_avg[mv_num] = 0; //ERROR HERE? (yes, when mv_num == 1)
[...]
day[dayNumber].mov_avg[mv_num] = sum_of_elems / smaSize;
[...]
day[dayNumber].mov_avg[mv_num] = sum_of_elems / smaSize;
[...]
if (day[dayNumber].mov_avg[1] != 0) 
    if (day[dayNumber].mov_avg[0] < day[dayNumber].mov_avg[1] && holdingLong == true) 
[...]

尝试定义

float mov_avg[2];

【讨论】:

以上是关于C++程序运行内存错误的主要内容,如果未能解决你的问题,请参考以下文章

内存位置的 C++ 范围错误?

C# & C++:“试图读取或写入受保护的内存”错误

引发C++程序内存错误的常见原因分析与总结

引发C++程序内存错误的常见原因分析与总结

挣扎 - 又一个内存损坏问题,错误分配(C++,VS 2008)

克服 C++ 中的错误内存分配