此分配的目的是从包含城市状态的文件中读取一行,后跟两行包含纬度和经度坐标的行。然后我们需要完全按照下面的描述动态分配结构来存储这些坐标。最后,我们将地标导出为google earth使用的KML格式。
此时我可以从我的结构中正确编写KML。然而,在我的grow_whole函数中有几个脏for循环(见下文)。问题是我稍后释放所有已分配的指针。 (相信我,它存在以下的顺序粘贴它)。我很确定问题是堆损坏。然而,我一直在这方面工作太久,我觉得它可以更简单。
文件格式。 (其中有150个。)
city, state
40 30 N
40 20 W
Wholesome_t只是一个容器,可以保存有关地标结构数量的信息以及指向第一个地标的指针。 Landmark_t保存着指向字符的指针,这些字符分配了他们需要包含解析的城市名称所需的空间量等等。
struct landmark_t {
char *city;
char *state;
char *country;
float longitude;
float latitude;
};
struct wholesome_t {
struct landmark_t *landmarks;
int landcount;
int landmax;
};
下面是处理读取行并将它们发送到正确解析器的代码块。
最初有益健康的是malloc' d并且地标指针设置为NULL。 然后我们malloc空间为2个标志性结构,并开始下面的while循环。
struct landmark_t *land = NULL;
int coorflag = 0;
int flagcount = 0;
//Parse lines
while(fgets(buf, LEN, in)){
//Does that thing where we realloc
if(whole->landcount == whole->landmax){
grow_whole(whole);
}
//remove trailing newline
buf[strcspn(buf, "\n")] = 0;
if(!coorflag){//Check to see if we are on a flag or coordinate
//set land to be the pointer to our next empty landmark struct
land = whole->landmarks + (sizeof(struct landmark_t) * whole->landcount);
set_city_state_country(buf, land);
coorflag = 1; //Set flag to get a coordinate line next
}else{//We are on a coordinate line which will use
//the same land struct pointer as above
if(!flagcount){//Have we seen a coordinate line already?
land->latitude = number_muncher(buf);
flagcount = 1;
}else{//We have seen a coordinate line
land->longitude = number_muncher(buf);
//We are done filling this structure. Reset flags and move to the next.
flagcount = 0;
coorflag = 0;
whole->landcount++;
}
}
}
问题在于grow_whole。我之前遇到过一个问题,在运行realloc之后,第一个地标结构将包含正确分配的指针,但是在它之后的任何地方,直到靠近文件末尾的某个地方,所有城市,州和国家以及经度和纬度的指针都将是被淘汰了。我添加了for循环,在我们重新分配之前保存了所有指向数组的指针,然后将这些指针重写回正确的结构。
void grow_whole(struct wholesome_t *whole)
{
//First collect all of the pointers inside our current landmark structs.
struct landmark_t *land = NULL;
char *city[whole->landcount];
char *state[whole->landcount];
char *country[whole->landcount];
float longitude[whole->landcount];
float latitude[whole->landcount];
for (int i = 0; i < whole->landcount; i++){
land = whole->landmarks + (sizeof(struct landmark_t) * i);
city[i] = land->city;
state[i] = land->state;
country[i] = land->country;
longitude[i] = land->longitude;
latitude[i] = land->latitude;
}
land = realloc(whole->landmarks, (GROW + whole->landmax) * sizeof(struct landmark_t));
if(land == NULL){
printf("Error in grow_whole.\n");
return;
}else{whole->landmarks = land;}
//Update landmax to represent aftergrow.
whole->landmax = GROW + whole->landmax;
//Refill all of the re allocated structs with their pointers.
for (int i = 0; i < whole->landcount; i++){
land = whole->landmarks + (sizeof(struct landmark_t) * i);
land->city = city[i];
land->state = state[i];
land->country = country[i];
land->longitude = longitude[i];
land->latitude = latitude[i];
}
//Fill two new structs with blank data.
for(int i = whole->landcount; i < whole->landmax; i++){
land = whole->landmarks + (sizeof(struct landmark_t) * i);
empty_fill(land);
}
return;
}
在上面的while循环之后立即运行
fclose(in);
char *s = argv[1];
s = strtok(s, ".");
s = strncat(s, ".kml", 4);
FILE *out = fopen(s, "w");
//Finally done lets write some KML
kml_begin(out);
for (int i=0; i < whole->landcount; i++){
land = whole->landmarks + (sizeof(struct landmark_t) * i);
kml_placemark(out, i, land);
}
kml_end(out);
fclose(out);
tea_party(whole);//free land
free(whole->landmarks);
free(whole);
哪个到达kml_end(out)。 (我知道因为我的格式正确,格式正确.kml文件)但是在tea_party期间,我得到了一个seg_fault。
void tea_party(struct wholesome_t *whole)
{
struct landmark_t *land = NULL;
for (int i = 0; i < whole->landcount; i++){
land = whole->landmarks + (sizeof(struct landmark_t) * i);
printf("here\n");
free(land->city);
printf("here2\n");
free(land->state);
printf("here3\n");
free(land->country);
}
return;
}
它出现在我们的第二个里程碑结构中。
land = whole->landmarks + sizeof(struct landmark_t)
并且在free(land-&gt;状态)发生(因为我在这里看到第一个结构的1-3,然后在seg错误之前的1-2)。
即使我尝试在seg故障之前打印land-&gt;状态,它也只是将seg故障向上移动。
答案 0 :(得分:0)
在进行指针运算时,您不必按sizeof(struct landmark_t)
缩放偏移量 - 编译器已经为您执行了此操作!
如果指针p
在数组中,则下一个数组元素位于p + 1
。就这么简单。
此外,当您应该创建一个记录数组时,您似乎创建了一个数组记录。但这是一个不同的问题。