注意:我正在使用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就会变成乱码。随着越来越多的东西被调用,甚至更多的阵列变成了胡言乱语。这很奇怪,我不知道发生了什么......有没有人有任何想法?感谢。
答案 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::vector
和std::string
这样的东西,并避免直接使用数组。
<强>更新强>
正如Zack指出的那样,你将返回指向堆栈分配变量的指针,这些变量将在set_up_temp
函数返回时消失。此外,您使用的fgets
并没有按照您的想法执行操作,而是以 HORRIBLE 代码开头。请阅读fgets
的文档,并问问自己代码的作用。
答案 2 :(得分:2)
您正在为118个元素分配一个包含空格的数组,但代码设置了128个元素,从而覆盖了阵列后面发生的任何事情。
另外正如其他人所指出的那样,你在数据指针中存储了对函数来说是临时的数据(一个禁忌)。
我的建议是在编程之前先阅读a good book关于C ++的内容,否则你无缘无故会让自己的生活更加艰难。 C ++不是一种你希望通过实验取得认真进步的语言。