【发布时间】:2017-12-19 18:20:10
【问题描述】:
我正在编写一个函数 (*rwObjects()),它将读取格式化文件并保存它的字符串,一次一个对象。不幸的是,我的学习有限制 - stdio.h、stdlib.h 和 string.h 几乎是我可以使用的所有内容。
问题是:每当我运行代码时,当它到达fclose(input) 时,VS17 会说我的项目触发了一个断点,然后打开一个标签,上面写着“wntdll.pdb not loaded”之类的。
问题是:如何不触发断点并正确关闭文件?或者,如果问题不在文件中,那么问题出在哪里?
代码(C):
#define _CRT_SECURE_NO_WARNINGS
#define cnCOUNTRY_LENGTH 3
#define cnOBJECT_NAME_LENGTH 30
#define cnOBJECT_MAX 1000
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//--Поле объекта objectType--
//Country (0) - строка названия страны
//ObjectName (1) - строка названия объекта
//Square (2) - площадь объекта
//Error (3) - ошибка в содержании строки
typedef enum IOOptions {Country, ObjectName, Square, Error} IOType;
//--Тип обрабатываемых объектов--
//char Country - строка названия страны
//char ObjectName - строка названия объекта
//int Square - площадь объекта
typedef struct object {
char Country[cnCOUNTRY_LENGTH];
char ObjectName[cnOBJECT_NAME_LENGTH];
int Square;
} objectType;
//--Копирование текущего элемента строки objects.txt--
//strMod - Строка, в которую идёт копирование
//strPos - Позиция в считываемой строке
//strBlueprint - Строка, из которой идёт копирование
//writeType - Поле объекта objectType. При "Country" - переводит вводимые символы в верхний регистр ('a' -> 'A' и т.д.)
void copyInputStr(char *strMod, int *strPos, char *strBlueprint, IOType writeType) {
for (*strPos; *strBlueprint != ' ' && *strBlueprint != '\n' && *strBlueprint != NULL; *strPos = *strPos + 1) {
*strMod = *strBlueprint;
if (writeType == Country) toupper(*strMod);
strBlueprint++; strMod++;
}
}
//--Запись текущего элемента строки objects.txt в текущий объект--
//strInput - Строка, из которой идёт запись
//objectOutput - Объект, в который идёт запись
//writeType - Поле объекта, в которое идёт запись
void writeObject(char *strInput, objectType *objectOutput, IOType writeType) {
if (writeType == Country)
strcpy(objectOutput->Country, strInput);
else if (writeType == ObjectName)
strcpy(objectOutput->ObjectName, strInput);
else if (writeType == Square)
objectOutput->Square = atoi(strInput);
else printf("Error 1. Invalid parameters");
}
//--Чтение objects.txt и запись в массив objectType--
//Возвращает указатель на первый элемент массива объектов
objectType *rwObjects() {
FILE *input = fopen("objects.txt", "r");
char objectQttStr[4], objectStr[38];
fgets(objectQttStr, 4, input);
objectType *objectList = (objectType *)malloc(atoi(objectQttStr)), *currentObject = objectList;
currentObject = (objectType *)malloc(atoi(objectQttStr));
for (int i = 0; i < atoi(objectQttStr); i++) {
fgets(objectStr, 38, input);
IOType inputType = Country;
for (int j = 0; objectStr[j] != NULL && objectStr[j] != '\n'; j++) {
char strBuf[cnOBJECT_NAME_LENGTH];
memset(&strBuf, 0, sizeof(strBuf));
copyInputStr(&strBuf, &j, &objectStr[j], inputType);
writeObject(&strBuf, currentObject, inputType);
inputType++;
}
currentObject++;
}
fclose(input); //this is where it happens
return objectList;
}
void main() {
objectType *objectList = rwObjects();
printf("");
}
这是一个令人困惑的程序,但我没有找到其他符合血腥规则的方法,所以让我们把编码风格放在一边,好吗?
另外,我知道如果它成功运行,什么都不会发生 - 这是设计使然。还没完呢。
编辑:不要担心输入数据的有效性。所有输入数据格式都在任务中明确说明,因此不需要检查。不过,对于好奇的人,这里是:
objects.txt:
3
USA WelfareArrangement 120
Rus PoiskZemli 30
usa asdfEstate 1
编辑 2:我停止使用 malloc 的那一刻,一切都很好。问题是 - 为什么会出现这样的问题,如果不使用 malloc,我将如何创建一个我需要的确切大小的数组,而不是每次创建最大大小?
【问题讨论】:
-
我想知道是否存在破坏
input的越界写入,可能在copyInputStr中? -
您的内存分配毫无意义。您似乎正在分配一个结构数组,但您每个只给它们一个字节。然后分配一个当前指针,然后用新的无用分配覆盖它。
-
代码应该检查
fgets(objectStr, 38, input);的返回值。 -
无论您使用什么警告级别,它都不够高。 A sample of warnings from clang here.
-
我认为您遇到了断言或 VS 错误,而不是断点。我不使用 VS,所以我无法进一步了解,但我怀疑您已经以某种方式损坏了输入指针并且 fclose 正在抱怨。
标签: c breakpoints stdio fclose