Sir*_*sis 1 c dynamic-memory-allocation
对于一门课程,我正在用 C 语言进行乘法表样式的练习。该代码功能齐全,但自动测试显示它分配了 416 个字节,而它应该只分配 376 个字节。这是值 a=2,b =9,c=11,d=17。我已经通过 valgrind 运行了代码,并打开了所有可能的额外细节,但它并没有真正帮助。
我尝试将标题行生成写入为主时间表创建的一部分,但它最终使用的内存比我当前的方法更多。
destroyTimes 函数也不应该有问题,因为 valgrind 没有报告任何泄漏。
这是 times.c
#include "times.h"
#include <stdlib.h>
#include <stdio.h>
Times* createTimes(uint a, uint b, uint c, uint d) {
int i,j;
int rows=d-c+2;
int cols=b-a+2;
Times* ret = malloc(sizeof(Times));
uint** kert = malloc(sizeof(uint*)*rows);
if (!ret) {
return NULL;
}
ret->a=a;
ret->b=b;
ret->c=c;
ret->d=d;
kert[0] = malloc(sizeof(uint)*(cols+1));
kert[0][0] = 1;
for(j=1;j<cols;j++) {
kert[0][j] = a;
a++;
}
a = ret->a;
for(i=1;i<rows;i++) {
kert[i] = malloc(sizeof(uint)*(cols+1));
for(j=0;j<cols;j++) {
kert[i][j] = c*kert[0][j];
}
c++;
};
ret->times = kert;
return ret;
}
void destroyTimes(Times* kt) {
uint i;
uint rows = kt->d - kt->c + 2;
if (kt == NULL) {
return;
}
for (i = 0; i < rows; i++) {
free(kt->times[i]);
}
free(kt->times);
free(kt);
}
Run Code Online (Sandbox Code Playgroud)
那么这里是 times.h
#ifndef TIMES_H
#define TIMES_H
typedef unsigned int uint;
struct Times {
uint a,b,c,d;
uint** times;
};
typedef struct Times Times;
Times* createTimes(uint,uint,uint,uint);
void destroyTimes(Times*);
#endif
Run Code Online (Sandbox Code Playgroud)
对于一门课程,我正在用 C 语言进行乘法表样式的练习。
好吧,所以你想学习 C。酷……
但请注意,学习 C 语言只是成功了一半。您还需要学习如何使用调试器。如何启动调试会话。如何设置断点。如何单步执行。如何检查变量值。等等...
现在似乎是这样做的好时机。
同时,C 还带有一个非常强大的内置调试器。它被称为printf(注1)。
执行时添加小的调试打印输出malloc将帮助您了解正在发生的情况。
例如:
printf("rows=%d cols=%d\n", rows, cols);
size_t total_alloc = 0;
size_t current_alloc = 0;
// Times* ret = malloc(sizeof(Times));
current_alloc = sizeof(Times);
total_alloc += current_alloc;
printf("Allocating %zu bytes for Times (total = %zu)\n", current_alloc, total_alloc);
Times* ret = malloc(current_alloc);
// uint** kert = malloc(sizeof(uint*)*rows);
current_alloc = sizeof(uint*)*rows;
total_alloc += current_alloc;
printf("Allocating %zu bytes for row-pointers (total = %zu)\n", current_alloc, total_alloc);
uint** kert = malloc(current_alloc);
// and likewise for all your malloc
Run Code Online (Sandbox Code Playgroud)
完成之后我可以运行你的程序并得到:
rows=8 cols=9
Allocating 24 bytes for Times (total = 24)
Allocating 64 bytes for row-pointers (total = 88)
Allocating 40 bytes for cols data in row 0 (total = 128)
Allocating 40 bytes for cols data in row 1 (total = 168)
Allocating 40 bytes for cols data in row 2 (total = 208)
Allocating 40 bytes for cols data in row 3 (total = 248)
Allocating 40 bytes for cols data in row 4 (total = 288)
Allocating 40 bytes for cols data in row 5 (total = 328)
Allocating 40 bytes for cols data in row 6 (total = 368)
Allocating 40 bytes for cols data in row 7 (total = 408)
Run Code Online (Sandbox Code Playgroud)
(见注2)
查看此输出时,很容易发现这些列有一些奇怪的地方。9列怎么需要40字节呢?每列 4.44 字节!没有意义。是时候看看专栏了malloc:
kert[i] = malloc(sizeof(uint)*(cols+1));
^^
oh, why did I add one here ???
I don't need 10 columns - only 9
Run Code Online (Sandbox Code Playgroud)
修复代码(即删除这+ 1两个地方)后,程序现在将生成:
rows=8 cols=9
Allocating 24 bytes for Times (total = 24)
Allocating 64 bytes for row-pointers (total = 88)
Allocating 36 bytes for cols data in row 0 (total = 124)
Allocating 36 bytes for cols data in row 1 (total = 160)
Allocating 36 bytes for cols data in row 2 (total = 196)
Allocating 36 bytes for cols data in row 3 (total = 232)
Allocating 36 bytes for cols data in row 4 (total = 268)
Allocating 36 bytes for cols data in row 5 (total = 304)
Allocating 36 bytes for cols data in row 6 (total = 340)
Allocating 36 bytes for cols data in row 7 (total = 376)
Run Code Online (Sandbox Code Playgroud)
教训:一些调试打印对于查找错误非常有用。但展望未来,学习如何使用真正的调试器非常重要。
注 1:不,printf不是调试器。只是开玩笑......printf不能替代真正的调试器,但进行小型调试打印输出实际上对于查找小程序中的错误非常有用。
注 2:在你的原始代码中,我得到了 408 个字节,而你得到了 416 个字节。不确定为什么不同,但也许你的编译器在结构中添加了 8 个字节的填充Times
一点额外
uint rows = kt->d - kt->c + 2;
if (kt == NULL) { <--- Too late... you all ready did the dereference
return;
}
Run Code Online (Sandbox Code Playgroud)
NULL 的检查必须在之前 kt->d
| 归档时间: |
|
| 查看次数: |
100 次 |
| 最近记录: |