访问导致运行时错误的动态数组

Posted

技术标签:

【中文标题】访问导致运行时错误的动态数组【英文标题】:Accessing a Dynamic Array causing a runtime error 【发布时间】:2017-04-27 21:10:26 【问题描述】:

我一直在搞乱动态内存,结果碰上了一堵巨大的墙。

我正在尝试创建一个程序,用户可以在其中输入任意数量的字符串,然后可以随时退出,但是在输入第二个字符串后,程序崩溃而没有给我任何特定的错误消息。

#include "stdafx.h"
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "new"

int _tmain(int argc, _TCHAR* argv[])

    //Variables
    int i=0,end=0,requiresSize=1;
    char ** temp;
    char  item[256]="a";
    char ** requires;


    //Initialize each element in requiers
    requires = new char * [requiresSize];
    for(int j=0;j<requiresSize*2;j++)
        requires[j]= new char[256];
    


    while(strcmp(item,"q-"))
        end=0;
        printf("Enter h- for help.\nEnter q- to quit.\n");
        printf("Please enter a string\n");
        gets_s(item);
        if(!strcmp(item,"h-"))
            printf("Enter a string to add to the list.\nEnter p- to print the list.\n");
            end=1;
           
        if(!strcmp(item,"q-"))
            break;
        
        if(!strcmp(item,"p-"))
            if(requires[0]!=NULL)
                for(int j=0;j<requiresSize;j++)
                    printf("%d. %s\n",j,requires[j]);
                
            
            end=1;
        
        while(end==0)
                printf("check1:i=%d\n",i);
            //if search index is larger than size of the array,reallocate the array
            if(i>= requiresSize)
                temp = new char * [requiresSize*2];
                //Initialize each element in temp
                printf("check2:temp initalized\n");
                for(int j=0;j<requiresSize*2;j++)
                    temp[j]= new char[256];
                
                printf("check3:temp itmes initialized\n");
                for(int j =0;j<requiresSize;j++)
                    //for each element in requires, copy that element to temp
                    temp[j]=requires[j];
                
                printf("check4:copied requires into temp\n");
                delete * requires;
                requires = temp;
                printf("check5:deleted requires and set requires equal to temp\n");
                delete  temp;
                requiresSize = requiresSize *2;         
            
                printf("check6:\n");
            //if the index at requires is not empty, check to see if it is the same as given item
            if(requires[i]!= NULL)
                printf("check8:index at requires is not empty\n");
                //I know the error occurs here, something to do with accessing requires[i]
                if(!strcmp( item,  requires[i]))
                printf("check9:index at requires is the same as item\n");
                    //if they are the same, break out of the loop, item is already included
                    break;
                else
                printf("check10:index at requires is different\n");
                    //otherwise, increase the index and check again (continue loop)
                    i++;
                    break;
                
            else
                printf("check11:index at requires is null, item added\n");
                //if the index is empty, add the item to the list and break out of loop
                requires[i]=  item;
                break;
            
                printf("check7\n");

        
    
    delete requires;
    return 0;

提前谢谢你。

【问题讨论】:

使用 std::string - 您的代码基本上是 C 语言,带有新的替换 malloc。 顺便说一句,您的第一个 for 循环已经访问了您分配的数组超出其边界并调用 未定义的行为 #include "stdafx.h" 的存在表明您正在使用 Visual Studio。 Visual Studio 拥有市场上最好的调试器之一,即使不是最好的。我建议利用它来单步执行代码,并留意程序开始偏离预期的位置。 我正在尝试创建一个程序,用户可以在其中输入任意数量的字符串 -- std::vector&lt;std::string&gt;。你写的所有代码都被那个替换了。 Example。将其与您正在尝试做的事情进行比较。 【参考方案1】:

你需要意识到像temp = requires这样的赋值语句(在这种情况下)只是复制指针,所以temp现在指向与requires相同的内存位置;它不会复制该内存。

这会导致两个问题:

    您正在为temp 的每个元素分配新的256 字符数组,然后重新分配temp 中的每个字符* 以指向不同的位置,从而泄漏所有内存;现在无法引用新分配的内存,因此您无法释放它。

    1234563 ,同样,requires 现在也指向)。

另外,如果你使用new[] 分配一个数组,你必须使用delete[] 来释放它。所以requires = new char * [requiresSize]; 要求你在程序结束时使用delete [] requires;,而不仅仅是delete requires;requires 的每个 256 字符元素都相同。

因此,将temp[j]=requires[j]; 替换为对strcpy(或strncpy)的适当调用。并且不要删除temp;最后的 delete [] requires; 将处理这个问题,因为它现在指向那段内存。

【讨论】:

那么数组将如何重新分配?如果我在保存数据的同时用 new 重新分配 temp(或其指向的内存),那不会覆盖以前的数据吗? 没有。 temp 只是一个指针;它的值是它指向的内存中的位置。当您为其分配一个新值时,无论是通过将其他指针的值复制给它,还是将 new/new[] 的结果分配给它,它都不会影响 temp 最初指向的内存。同样,requires = temp; 之类的语句仅使两个指针指向同一内存区域(temp 最初指向的内存;它不会释放任何内存。 那么如何扩展temp指向的已分配内存呢? 你会做你现在正在做的事情:分配新内存到temp,复制来自required的指针,释放required,此时temp就可以了下次再用。 我注释掉了`delete temp;`,这似乎一切正常。也许您可以帮助我弄清楚为什么当我尝试访问数组中的数据时,我会得到随机符号。我认为这可能不值得单独提出一个问题。

以上是关于访问导致运行时错误的动态数组的主要内容,如果未能解决你的问题,请参考以下文章

使用数组重载运算符“=”会导致运行时错误 C++

GCC 错误 - 在 constexpr 中输入/递减数组访问

主属性不是在 aspx 设计器中自动生成导致运行时错误

异常断言日志

二维数组C++的动态分配

运行时多态性 - 箭头运算符访问错误的成员?