1

注意:我使用的是 c++ 编译器,因此我可以使用按引用传递

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

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

typedef struct{
    char * name;
    char * symbol;
    int atomic_number;
    double atomic_weight;
    int electrons;
    int neutrons;
    int protons;
} 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 就会变成乱码。随着越来越多的事情被调用,更多的数组变成了乱码。这很奇怪,我不知道发生了什么......有人知道吗?谢谢。

4

3 回答 3

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调用者中最接近堆栈指针的部分,因此最有可能被后续函数调用覆盖。

于 2013-04-25T17:35:59.900 回答
3

随意检查会产生这样的结果:

char temp_array[826][20];

...

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

您的代码可能允许i成为826. 这意味着您正在访问temp_array. 这是一个过去的结束。哎呀。

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

这个故事的寓意:注意你的索引,因为你使用 C++,所以要利用std::vectorstd::string避免直接使用数组。

更新 正如 Zack 所指出的,您正在返回指向堆栈分配变量的指针,这些变量将在set_up_temp函数返回时消失。此外,fgets您使用的代码并没有按照您的想法执行,而且一开始就是可怕的代码。请阅读文档fgets并问问自己你的代码是做什么的。

于 2013-04-25T17:33:49.680 回答
2

您正在为一个包含 118 个元素的空间分配一个数组,但代码设置了 128 个元素,因此覆盖了数组之后发生的任何内容。

此外,正如其他人指出的那样,您在数组中存储了指向函数临时数据的指针(禁止)。

我的建议是在编程之前先阅读一本关于 C++ 的好书,否则你会无缘无故地让你的生活变得更艰难。C++ 不是一种您可以希望通过实验取得重大进展的语言。

于 2013-04-25T17:34:59.383 回答