如果引入多对数据,为什么这个程序会崩溃?

时间:2014-04-16 01:37:40

标签: c++ arrays

我正在编写程序,以便在动态分配的数组中引入,然后再打印它。如果我只介绍一组值,一切都很好,但如果我引入更多的那一对值,程序就会崩溃。

#include <iostream>
#include <stdlib.h>

using namespace std;

int *a, *b, m;
void askData(int **a, int **b);
void printData(int **a, int **b);

int main(){

    bool control = true;

    do{
        cout <<" ************* MENU ************* "<< endl;
        cout <<"    1.-  Ask for values  "<< endl;
        cout <<"    2.-  Print values  "<< endl;
        cout <<"    3.-  Exit "<< endl;

        cout << "Select one option: " << endl;
        int n;
        cin >> n;

        switch(n){
        case 1:
            askData(&a,&b);
            cout << endl;
            break;
        case 2:
            printData(&a,&b);
            break;
        default:
            cout << "Exit" << endl;
            break;
        }

        system("pause");
        system("cls");
        if(n == 3){
            control = false;
        }
    }while(control);
    return 0;
}

void askData(int **a, int **b){
    cout << endl << "Enter the number of pairs of data: ";
    cin >> ::m;
    int z = ::m;

    *a = new int[z];
    *b = new int[z];

    for(int i=0; i<z; i++){
        cout << "Enter V[" << i <<"], Enter T[" << i << "]:?";
        cin >> *a[i] >> *b[i];
    }

    delete [] a;
    delete [] b;
}

void printData(int **a, int **b){
    for(int i=0; i < m; i++){
        cout << *a[i] << " " << *b[i] << endl;
    }
}

4 个答案:

答案 0 :(得分:2)

你试图在释放它(悬空指针)之后读取内存,这将有未定义的行为

您的函数 askData 正在分配内存并填充数据。但是在此函数的末尾,您将释放存储在全局变量 a &amp;中的内存。 b

现在在 printData ()函数内部,您正在传递要读取的已释放内存指针。这会导致问题。

<强> EDIT1

我们应该避免使用原始指针而不是使用C ++提供的智能指针。在这种情况下,您不必担心手动内存管理。

<强> EDIT2

您的程序正在尝试写入 a &amp; b (指向指针的指针)。无论如何,对于您的程序,您可以删除传递给不同函数的参数,因为它们是全局变量。但我建议你开始使用 std :: vector smart_pointer

了解如何使用ISOCPP FAQ链接中的这些概念:

http://isocpp.org/wiki/faq/freestore-mgmt#memory-leaks

void askData(){
    a = new int[z];
    b = new int[z];
    for(int i=0; i<z; i++){
        cout << "Enter V[" << i <<"], Enter T[" << i << "]:?";
        cin >> a[i] >> b[i];
    }
}

void printData(){
    for(int i=0; i < m; i++){
        cout << a[i] << " " << b[i] << endl;
    }
    delete [] a;
    delete [] b;
}

答案 1 :(得分:2)

askData函数中创建动态数组时,需要将数组取消引用为:

for(int i=0; i<z; i++){
    cout << "Enter V[" << i <<"], Enter T[" << i << "]:?";
    cin >> (*a)[i] >> (*b)[i];
}

对于printData函数,您需要将它们取消引用为:

for(int i=0; i < m; i++){
    cout << (*a)[i] << " " << (*b)[i] << endl;
}

请注意,当您使用

*a = new int[z];
*b = new int[z];

*a*b是指向大小为z的整数数组的指针。并且ab是指向函数参数列表中定义的指针的指针。

您还需要按照其他人的建议将这两行注释掉

//delete [] a;
//delete [] b;

不要忘记在printData结束时释放记忆。

答案 2 :(得分:0)

delete [] a;
delete [] b;

删除了内存,即不再分配数组并从堆中删除数据。

答案 3 :(得分:0)

首先,我建议您将全局变量置于本地并初始化它们。更容易解决出错的问题。

int *a = 0, *b = 0, m;

要拉出局部变量,您需要为askData()添加第三个参数,并为数组的大小添加printData()

void askData(int **a, int **b, int &m);  // m is by reference because you want to return the size
void printData(int **a, int **b, int m);

方法askData()应该检查ab是否已经指向内存,在分配更多内容之前应该释放内存

    if( *a != 0 )  
    { 
        delete [] *a;   
    }
    *a = new int[m];

    if( *b != 0 ) 
    { 
        delete [] *b; 
    }
    *b = new int[m];

由于您传递的是m,因此您无需声明z

    cout << endl << "Enter the number of pairs of data: ";
    cin >> m;  // Just use m

    ...

    for(int i=0; i<m; i++){
        cout << "Enter V[" << i <<"], Enter T[" << i << "]:?";
        cin >> (*a)[i] >> (*b)[i];
    }

接下来,您的程序会分配您需要处理的内存。这不应该发生在askData(),但是在你知道你不再需要那个记忆之后。在您的情况下,我建议将其放在main()的末尾附近。在尝试删除它们之前,您应该检查它们是NULL,还是0

if( a != 0 )
{
    delete [] a;   // No asterick because these are `int*`
}

if( b != 0 )
{
    delete [] b;
}

你修改的程序看起来像这样

#include <iostream>
#include <stdlib.h>

using namespace std;

void askData(int **a, int **b, int &m);
void printData(int **a, int **b, int m);

int main(){
    int *a = 0, *b = 0, m;  // These are now local, much better 
    bool control = true;

    do{
        cout <<" ************* MENU ************* "<< endl;
        cout <<"    1.-  Ask for values  "<< endl;
        cout <<"    2.-  Print values  "<< endl;
        cout <<"    3.-  Exit "<< endl;

        cout << "Select one option: " << endl;
        int n;
        cin >> n;

        switch(n){
        case 1:
            askData(&a,&b, m);
            cout << endl;
            break;
        case 2:
            printData(&a,&b, m);
            break;
        default:
            cout << "Exit" << endl;
            break;
        }

        system("pause");
        system("cls");
        if(n == 3){
            control = false;
        }
    }while(control);

    if( a != 0 )
    {
        delete [] a; 
    }

    if( b != 0 )
    {
        delete [] b;
    }

    return 0;
}

void askData(int **a, int **b, int &m){

    cout << endl << "Enter the number of pairs of data: ";
    cin >> m;

    if( *a != 0 ) 
    { 
        delete [] *a; 
    }
    *a = new int[m];

    if( *b != 0 ) 
    { 
        delete [] *b; 
    }
    *b = new int[m];

    for(int i=0; i<m; i++){
        cout << "Enter V[" << i <<"], Enter T[" << i << "]:?";
        cin >> (*a)[i] >> (*b)[i];
    }
}

void printData(int **a, int **b, int m){

    for(int i=0; i < m; i++){
        cout << (*a)[i] << " " << (*b)[i] << endl;
    }
}