在我的程序开始时,我创建了这个结构:
struct directive {
char gate[17];
int n;
int s;
int *inputs;
int *outputs;
int *selectors;
};
这里包括我的全部主要功能:
int main(int argc, char** argv) {
if (argc - 1 != 1) {
printf("Invalid number of argumentsn");
return 0;
}
//get file, return if invalid path
FILE *file = fopen(argv[1], "r");
if (!file) {
printf("Invalid inputn");
return 0;
}
//make temp of circuit with struct directive
int scount = 0;
struct directive* temp = NULL;
int size = 2;
int icount = 0;
int ocount = 0;
int tcount = 0;
char dir[17];
char **names;
int *values;
//get INPUT info
fscanf(file, " %s", dir);
fscanf(file, "%d", &icount);
size += icount;
names = malloc(size * sizeof(char *));
names[0] = malloc(2 * sizeof(char)); //MALLOC
strcpy(names[0], "0");
names[1] = malloc(2 * sizeof(char)); //MALLOC
strcpy(names[1], "1");
int i;
for (i = 0; i < icount; i++) {
names[i + 2] = malloc(17 * sizeof(char));
fscanf(file, "%*[: ]%16s", names[i + 2]);
}
//get OUTPUT info
fscanf(file, " %s", dir);
fscanf(file, "%d", &ocount);
size += ocount;
names = realloc(names, size * sizeof(char *));
for (i = 0; i < ocount; i++) {
names[i + icount + 2] = malloc(17 * sizeof(char));
fscanf(file, "%*[: ]%16s", names[i + icount + 2]);
}
//get temp
struct directive step;
while (!feof(file)) {
int numInputs = 2, numOutputs = 1;
int sc = fscanf(file, " %s", dir);
if (sc != 1) {
break;
}
scount++;
step.n = 0;
step.s = 0;
strcpy(step.gate, dir);
if (strcmp(dir, "NOT") == 0) {
numInputs = 1;
}
if (strcmp(dir, "PASS") == 0) {
numInputs = 1;
}
if (strcmp(dir, "DECODER") == 0) {
fscanf(file, "%d", &numInputs);
step.n = numInputs;
numOutputs = pow(2, numInputs);
}
if (strcmp(dir, "MULTIPLEXER") == 0) {
fscanf(file, "%d", &numInputs);
step.s = numInputs;
numInputs = pow(2, numInputs);
}
step.inputs = malloc(numInputs * sizeof(int));
step.outputs = malloc(numOutputs * sizeof(int));
step.selectors = malloc(step.s * sizeof(int));
char v[17];
for (i = 0; i < numInputs; i++) {
fscanf(file, "%*[: ]%16s", v);
step.inputs[i] = indexOf(size, names, v);
}
for (i = 0; i < step.s; i++) {
fscanf(file, "%*[: ]%16s", v);
step.selectors[i] = indexOf(size, names, v);
}
for (i = 0; i < numOutputs; i++) {
fscanf(file, "%*[: ]%16s", v);
int idx = indexOf(size, names, v);
if (idx == -1) {
size++;
tcount++;
names = realloc(names, size * sizeof(char *));
names[size - 1] = malloc(17 * sizeof(char));
strcpy(names[size - 1], v);
step.outputs[i] = size - 1;
}
else {
step.outputs[i] = idx;
}
}
//add step to list of temp
if (!temp) {
temp = malloc(sizeof(struct directive));
} else {
temp = realloc(temp, scount * sizeof(struct directive));
}
temp[scount - 1] = step;
}
// initialize values array
values = malloc(size * sizeof(int));
resetValues(size, values);
while(1 < 2) {
//print inputs
for (i = 0; i < icount; i++) {
printf("%d ", values[i + 2]);
}
printf("|");
//run through temp, calculate outputs
for (i = 0; i < scount; i++) {
struct directive step = temp[i];
if (strcmp(step.gate, "NOT") == 0) {
NOT(values, step.inputs[0], step.outputs[0]);
}
if (strcmp(step.gate, "AND") == 0) {
AND(values, step.inputs[0], step.inputs[1], step.outputs[0]);
}
if (strcmp(step.gate, "OR") == 0) {
OR(values, step.inputs[0], step.inputs[1], step.outputs[0]);
}
if (strcmp(step.gate, "NAND") == 0) {
NAND(values, step.inputs[0], step.inputs[1], step.outputs[0]);
}
if (strcmp(step.gate, "NOR") == 0) {
NOR(values, step.inputs[0], step.inputs[1], step.outputs[0]);
}
if (strcmp(step.gate, "XOR") == 0) {
XOR(values, step.inputs[0], step.inputs[1], step.outputs[0]);
}
if (strcmp(step.gate, "PASS") == 0) {
PASS(values, step.inputs[0], step.outputs[0]);
}
if (strcmp(step.gate, "DECODER") == 0) {
DECODER(values, step.n, step.inputs, step.outputs);
}
if (strcmp(step.gate, "MULTIPLEXER") == 0) {
MUX(values, step.s, step.inputs, step.selectors, step.outputs[0]);
}
}
//print outputs
for (i = 0; i < ocount; i++) {
printf(" %d", values[icount + i + 2]);
}
printf("n");
if (!incrementInputs(values, icount)) {
break;
}
}
for (i = 0; i < icount; i++) {
free(names[i + 2]);
}
for (i = 0; i < ocount; i++) {
free(names[i + icount + 2]);
}
free(step.inputs);
free(step.outputs);
free(step.selectors);
free(names[0]);
free(names[1]);
free(values);
free(temp);
return 0;
}
我遇到的问题是,在编译时,我的地址清理程序告诉我,我在第203行和第204行有内存泄漏,这是以下mallocs:
names = realloc(names, size * sizeof(char *));
names[size - 1] = malloc(17 * sizeof(char));
你可以看到,我释放了我分配给的三行,那么它实际上没有释放的原因是什么?我是否必须循环浏览一些内容并免费使用,因为我在主要内容之后做了其他事情?
您在循环中分配内存,但只释放上次迭代中获得的内容:
...
while (!feof(file)) {
...
step.inputs = malloc(numInputs * sizeof(int));
step.outputs = malloc(numOutputs * sizeof(int));
step.selectors = malloc(step.s * sizeof(int));
...
}
...
free(step.inputs);
free(step.outputs);
free(step.selectors);
...
由于while (!feof(file)) { ... }
循环的最后一次迭代,这组调用只是释放step
的最后一个值。
free(step.inputs);
free(step.outputs);
free(step.selectors);
每次迭代,step
都被复制到temp
的一个元素,因此在释放temp
之前必须释放每个元素的成员。
for (int i = 0; i < scount; i++) {
free(temp[i].inputs);
free(temp[i].outputs);
free(temp[i].selectors);
}
其他人已经指出了主要问题,所以我不重复了,但我想给出一些提示,使分配更加安全。
当您malloc()
并且需要提供数据大小时,使用sizeof(type)
没有错,但如果您的类型错误,就像一个简单的打字错误一样,您会得到错误的内存量。即使你没有犯任何错误,如果你在以后的某个时候改变指针类型,它也会咬你。编译器不会检查你给malloc()
的大小是否正确(实际上不能(,所以你不会收到任何关于你为错误类型分配大小的地方的警告。
因此,在等分配中
names = malloc(size * sizeof(char *));
names[0] = malloc(2 * sizeof(char));
names[i + 2] = malloc(17 * sizeof(char));
step.inputs = malloc(numInputs * sizeof(int));
step.outputs = malloc(numOutputs * sizeof(int));
step.selectors = malloc(step.s * sizeof(int));
所有的CCD_ 9都是潜在的漏洞隐藏场所。
相反,你可以从分配给的指针中获得大小。当然,有时你需要分配一些东西,但你没有分配给的变量——将分配的内存发送给一个函数或类似的函数,但99%的情况下,如果你给一个变量分配malloc。您还可以使用sizeof
获取变量指向的类型的大小。sizeof
运算符有两种风格。一个采用类型sizeof(type)
,另一个采用表达式sizeof expressions
或sizeof(expression)
;括号在这里是可选的。
您可以将上面的分配更改为:
names = malloc(size * sizeof *names);
names[0] = malloc(2 * sizeof *names[0])
names[i + 2] = malloc(17 * sizeof *names[i + 2])
step.inputs = malloc(numInputs * sizeof *step.inputs);
step.outputs = malloc(numOutputs * sizeof *step.outputs);
step.selectors = malloc(step.s * sizeof *step.selectors);
你需要在这里取消引用变量,因为否则你会得到指针的大小,而不是它指向的东西,但不要担心这个取消引用。编译器不会发出实际取消引用的代码,考虑到指针还没有初始化,这在任何情况下都是灾难性的。不,指针只是计算出表达式的类型并从中获取大小。这样,分配和您想要分配空间的类型保持一致。
另一件事是你做的realloc()
:
names = realloc(names, size * sizeof(char *));
诚然,它不太可能失败,但如果失败了,realloc()
将返回NULL
,如果失败,它就没有释放输入指针。如果这个realloc()
失败,那么names
中就会有NULL
,并且names
之前指向的内存也会泄漏。
出于这个原因,通常不应该将realloc()
的结果直接分配给输入指针。最好分配给一个临时变量,检查分配是否失败,如果没有,则可以分配给要保存结果的变量。
char **tmp = realloc(names, size * sizeof *tmp);
if (!tmp) abort(); // handle alloc failure
names = tmp;
当然,这取决于您是否计划处理分配失败。我在这里只使用abort()
,您可以在不分配给tmp
变量的情况下执行同样的操作
names = realloc(names, size * sizeof *tmp);
if (!names) abort(); // handle alloc failure
如果您在桌面上运行,分配错误不太可能成为问题,并且用一些适当的错误消息终止程序是一个简单的修复方法,可能很好。