100%的数组在函数中正确,75%的数组在CALLING函数中正确 - C

时间:2013-04-25 17:28:06

标签: c++ c arrays struct output

注意:我正在使用c ++编译器,因此我可以使用传递引用

我有一个奇怪的问题,我真的不知道发生了什么。

基本上,我有一个文本文件:http://pastebin.com/mCp6K3HB 我正在将文本文件的内容读入一个原子数组:

typedef struct{
    char * name;
    char * symbol;
    int atomic_number;
    double atomic_weight;
    int electrons;
    int neutrons;
    int protons;
} atom;

这是我对atom的类型定义。

void set_up_temp(atom (&element_record)[DIM1])
{
    char temp_array[826][20];
    char temp2[128][20];
    int i=0;
    int j=0;
    int ctr=0;

    FILE *f=fopen("atoms.txt","r");

    for (i = 0; f && !feof(f) && i < 827; i++ ) 
    {
        fgets(temp_array[i],sizeof(temp_array[0]),f);
    }

    for (j = 0; j < 128; j++)
    {
        element_record[j].name = temp_array[ctr];
        element_record[j].symbol = temp_array[ctr+1];
        element_record[j].atomic_number = atol(temp_array[ctr+2]);
        element_record[j].atomic_weight = atol(temp_array[ctr+3]);
        element_record[j].electrons = atol(temp_array[ctr+4]);
        element_record[j].neutrons = atol(temp_array[ctr+5]);
        element_record[j].protons = atol(temp_array[ctr+6]);
        ctr = ctr + 7;
    }

    //Close the file to free up memory and prevent leaks
    fclose(f);
} //AT THIS POINT THE DATA IS FINE

这是我用来读取数据的函数。当我调试这个函数,并让它运行到最后,我使用调试器检查它的内容,并且数组有100%正确的数据,也就是说,所有元素都是它们应该相对于文本文件。 http://i.imgur.com/SEq9w7Q.png此图片显示了我在说什么。在左侧,所有元素,0,最多127,是完美的。 然后,我转到我正在调用它的函数。

atom myAtoms[118];
set_up_temp(myAtoms); //AT THIS POINT DATA IS FINE
region current_button_pressed; // NOW IT'S BROKEN
load_font_named("arial", "cour.ttf", 20); 
panel p1 = load_panel("atomicpanel.txt");   
panel p2 = load_panel("NumberPanel.txt");

一旦调用ANYTHING,在我调用set_up_temp之后,我阵列的元素103到127就会变成乱码。随着越来越多的东西被调用,甚至更多的阵列变成了胡言乱语。这很奇怪,我不知道发生了什么......有没有人有任何想法?感谢。

3 个答案:

答案 0 :(得分:7)

for (j = 0; j < 128; j++)
{
    element_record[j].name = temp_array[ctr];

您正在存储,然后返回指向堆栈中temp_array的指针。从函数返回的那一刻,temp_array所有变得无效 - 在该点之后取消引用任何指针的未定义行为。 “未定义的行为”包括你仍然可以毫无困难地读取元素0到102的可能性,但正如你所说,103到127转向乱码。您需要为这些字符串分配空间,这些字符串将与atom对象一样长。正如您所说,您使用的是C ++,最简单的解决方法是将char *个成员更改为std::string。 (如果您不想使用std::string,第二个最简单的解决方法是使用strdup,但是您必须明确free该内存。)

这可能不是此代码中唯一的错误,但它可能是导致您眼前问题的错误。

如果你很好奇,数据结尾被破坏的原因是大多数(但不是全部)计算机,包括你正在使用的计算机,堆栈增长向下,即从高地址到低地址。但是,数组总是从低地址索引到高地址。因此,曾经是temp_array的内存区域的高端是最接近调用者中的堆栈指针的部分,因此最有可能被后续函数调用覆盖。

答案 1 :(得分:3)

随意检查产生了这个:

char temp_array[826][20];

...

for (i = 0; f && !feof(f) && i < 827; i++ )

您的代码可能会i成为826。这意味着您正在访问temp_array的第827个元素。这是一个结束的过程。哎呀。

此外,您正在分配一个包含118个原子(atom myAtoms[118];)的数组,但您在set_up_temp循环中的for (j = 0; j < 128; j++)内设置了128个原子。

这个故事的寓意:注意你的索引,因为你使用C ++来利用std::vectorstd::string这样的东西,并避免直接使用数组。

<强>更新 正如Zack指出的那样,你将返回指向堆栈分配变量的指针,这些变量将在set_up_temp函数返回时消失。此外,您使用的fgets并没有按照您的想法执行操作,而是以 HORRIBLE 代码开头。请阅读fgets的文档,并问问自己代码的作用。

答案 2 :(得分:2)

您正在为118个元素分配一个包含空格的数组,但代码设置了128个元素,从而覆盖了阵列后面发生的任何事情。

另外正如其他人所指出的那样,你在数据指针中存储了对函数来说是临时的数据(一个禁忌)。

我的建议是在编程之前先阅读a good book关于C ++的内容,否则你无缘无故会让自己的生活更加艰难。 C ++不是一种你希望通过实验取得认真进步的语言。