【问题标题】: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。将其与您正在尝试做的事情进行比较。

标签: c++ arrays memory dynamic


【解决方案1】:

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

这会导致两个问题:

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

  2. 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;`,这似乎一切正常。也许您可以帮助我弄清楚为什么当我尝试访问数组中的数据时,我会得到随机符号。我认为这可能不值得单独提出一个问题。
猜你喜欢
  • 2020-01-04
  • 1970-01-01
  • 2014-06-09
  • 2016-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-20
  • 1970-01-01
相关资源
最近更新 更多