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

Why is this program crashing if introduce more than one pair of data?

本文关键字:为什么 程序 崩溃 数据 如果      更新时间:2023-10-16

我正在编写程序以引入动态分配的数组,然后打印它。如果我只引入一组值,一切都很好,但是如果我引入超过 1 对值,程序就会崩溃。

#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;
    }
}

您正在尝试在释放内存(悬空指针(后读取内存,这将具有未定义的行为

您的函数 askData 正在分配内存并填充数据。但是在这个函数结束时,你正在释放存储在全局变量ab中的内存。

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

编辑1

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

编辑2

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

从 ISOCPP 常见问题解答链接中阅读有关如何使用这些概念的信息:

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;
}

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结束时释放内存。

正在执行

delete [] a;
delete [] b;

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

首先,

我要评论一下,您将全局变量本地化并初始化它们。 更容易排查出错的问题。

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;
    }
}