Lab0 C Programming Lab
一、关于实验环境的配置
下载地址15-213/14-513/15-513: Introduction to Computer Systems / Schedule Fall 2021 (cmu.edu)
Lab0 C Programming Lab(CMU)(CSAPP深入理解计算机系统)_虚拟机cprogramminglab-CSDN博客
环境我是用的wsl,用vscode远程链接,搭环境网上又很多帖子,我就不写了
make format
make test
二、内容
1.结构体
typedef struct list_ele {
char *value;
struct list_ele *next;
} list_ele_t;
typedef struct {
list_ele_t *head;
list_ele_t *tail;
size_t size;
} queue_t;
2.函数实现
queue_t *queue_new(void) {
queue_t *q = (queue_t *)malloc(sizeof(queue_t));
/* What if malloc returned NULL? */
if (q == NULL)
return NULL;
q->head = NULL;
q->tail = NULL;
q->size = 0;
return q;
}
void queue_free(queue_t *q) {
/* How about freeing the list elements and the strings? */
if (q == NULL)
return;
for (size_t i = 0; i < (q->size); i++) {
list_ele_t *tmp = q->head;
q->head = q->head->next;
free(tmp->value);
free(tmp);
}
/* Free queue structure */
free(q);
q = NULL;
}
bool queue_insert_head(queue_t *q, const char *s) {
if (q == NULL)
return false;
list_ele_t *newh;
/* What should you do if the q is NULL? */
newh = (list_ele_t *)malloc(sizeof(list_ele_t));
if (newh == NULL)
return false;
/* Don't forget to allocate space for the string and copy it */
newh->value = (char *)malloc(sizeof(char) * (strlen(s) + 1));
if (newh->value == NULL) {
free(newh);
return false;
}
strcpy(newh->value, s);
/* What if either call to malloc returns NULL? */
if (q->size == 0) {
q->head = newh;
q->tail = newh;
q->tail->next = NULL;
} else {
newh->next = q->head;
q->head = newh;
}
q->size++;
return true;
}
bool queue_insert_tail(queue_t *q, const char *s) {
if (q == NULL)
return false;
/* You need to write the complete code for this function */
list_ele_t *newh = (list_ele_t *)malloc(sizeof(list_ele_t));
if (newh == NULL)
return false;
newh->value = (char *)malloc(sizeof(char) * (strlen(s) + 1));
if (newh->value == NULL) {
free(newh);
return false;
}
strcpy(newh->value, s);
newh->next = NULL;
/* Remember: It should operate in O(1) time */
if (q->tail == NULL) {
q->head = newh;
q->tail = newh;
} else {
q->tail->next = newh;
q->tail = newh;
}
q->size++;
return true;
}
bool queue_remove_head(queue_t *q, char *buf, size_t bufsize) {
/* You need to fix up this code. */
if (q == NULL || q->size == 0)
return false;
// get headNode
list_ele_t *tmp = q->head;
q->head = q->head->next;
if (buf != NULL) {
strncpy(buf, tmp->value, bufsize - 1);
buf[bufsize - 1] = '\0';
}
free(tmp->value);
free(tmp);
q->size--;
return true;
}
size_t queue_size(queue_t *q) {
/* You need to write the code for this function */
/* Remember: It should operate in O(1) time */
if (q == NULL)
return 0;
return q->size;
}
void queue_reverse(queue_t *q) {
/* You need to write the code for this function */
if (q == NULL || q->size == 0)
return;
list_ele_t *oldh = q->head;
list_ele_t *oldt = q->tail;
list_ele_t *t1 = q->head;
list_ele_t *t2 = t1->next;
t1->next = NULL;
while (t2 != NULL) {
list_ele_t *tmp = t2->next;
t2->next = t1;
t1 = t2;
t2 = tmp;
}
q->head = oldt;
q->tail = oldh;
}
三、总结
-
malloc 和 delete动态内存管理
在堆上申请一块指定大小的内存,申请失败则会返回NULL,若成功记得初始化
delete成功后,要将指针设为NULL
-
内存泄露
struct Node { char *a; char *b; } 一个指针p指向该结构体,结构体有两个指针a、b分别指向char数组,如果直接free(p)会发生什么。 答:如果直接使用free(p)来释放指针p指向的结构体,那么只会释放结构体本身所占用的内存空间,也就是两个char指针本身所占内存,并不会释放结构体内部指针a和b所指向的内存空间。 这样会导致问题: ①结构体内部指针a和b所指向的内存空间没有被释放,造成内存泄漏。这会导致程序运行时占用的内存越来越多,最终可能耗尽系统资源。 ②在之后访问指针a和b时,由于这些指针已经无效,可能会导致程序崩溃或出现未定义行为。 正确的做法是,在释放指针p之前,先释放指针a和b所指向的内存空间,然后再调用free(p)释放结构体本身所占用的内存空间。可以使用free(a)和free(b)来释放指针a和b所指向的内存空间。 示例代码: free(a); free(b); free(p);
-
指针悬空和野指针
指针悬空和野指针是两个不同的概念,但都与指针使用错误相关。
而程序判断一个指针是否合法,通常都是使用if语句测试该指针是否为NULL来判断
指针悬空(Dangling Pointer):指针悬空是指在程序中存在指向已经释放的内存区域的指针。通常,在释放内存后,应将指针设置为 NULL,以避免指针悬空。如果继续使用指向已释放内存的指针,可能会导致未定义的行为,如访问无效的内存地址,导致程序崩溃或产生意料之外的结果。 int* p = new int(10); delete p; p = NULL; int value = *p; // 悬空指针访问,可能导致未定义的行为
野指针(Wild Pointer):野指针是指没有被初始化或者指向无效内存地址的指针。野指针通常是由于声明指针但未给其分配有效内存,或者在释放内存后未将指针设置为 NULL 而继续使用。野指针可能会导致程序崩溃、数据损坏或其他严重后果。 int* p; *p = 10; // 未初始化的指针,产生野指针
-
指针p是malloc的,现在q指向p,我free(q)然后q=NULL
虽然你对 q 进行了操作(释放内存并设置为 NULL),但这并不会影响 p 的值。p 仍然保持着之前分配的内存地址,但这是一个关键问题:尽管 p 的值没有改变,p 现在是一个悬挂指针,因为它指向的内存已经被释放。此时,通过 p 访问该内存也是未定义行为。
-
free(NULL)没问题,但变成NULL后就无法再p->next了