CS252 Mid
Premature Free: 过早释放内存
int *p = malloc(sizeof(int));
*p = 6; //将分配到内存中的值设置为6, p指针的值是*p = 6
free(p); //释放内存后,p虽然依然指向那块地址,但内存属于操作系统管理,p成为了一个悬空指针(dangling pointer),不是free(*p),因为p是指存储的地址,*p是p存储的地址里保存的值
printf("%d\n", *p);
Double Free
int *p = malloc(sizeof(int));
*p = 6;
free(p);
//free(p)后,p是dangling pointer,为了防止滥用,通常要加上p = NULL,手动清空指针
free(p);
Wild Free
int *p = malloc(sizeof(int));
*p = 6;
free(&p); // 释放了栈上的地址(指针本身的地址),应该是free(p)
int *p = malloc(sizeof(int));
*p = 6;
p = p + 1
free(p); //释放的并不是原始malloc返回的地址
Memory Smashing (Heap Buffer Overflow)
int *g = malloc(20 * sizeof(int)); //将指针看成一个数组,length = 20
g[20] = 40; //index <= 19
free(g);
Memory Leak:
int g = new int;
// new和malloc差不多,&g是指针本身的地址,g是存储值的地址,*g是值
//malloc靠free(g)来释放内存,new靠delete g来释放内存
*g = 40;
int g = new int;
*g = 41;
delete g;
int *g = malloc(sizeof(int));
*g = 6;
g = NULL;//原来存储6的地址丢失,永远无法有效free(g)
CPU-bound process是那种几乎需要一直使用CPU的进程,如果时间片(quantum)太短,会让其运行变慢。比如:
- CPU-bound 任务需要 100ms 才能完成,如果时间片是 100ms,一次就完成;如果时间片是 10ms,它需要被调度 10 次,每次都上下文切换;总耗时更长;进程调度效率更低 - 因此,quantum越短,context switch overhead越少
Multilevel Feedback Queue (MLFQ): 一种基于优先级的调度策略,低优先级队列中的进程容易一直被高优先级进程抢占,如果不加处理,这些低优先级进程可能永远得不到 CPU 时间,即发生饥饿(starvation)
- 奖励交互型进程(short quantum) -> 提高优先级
- 惩罚CPU密集型进程(长时间运行) -> 降低优先级
- 长时间低优先级,会增加其优先级
State: New -> Ready -> Running -> Exit
Or New -> Ready -> Running -> Waiting -> Ready
(大多数在waiting state)(处于Ready状态的进程不会直接进入waiting)
waiting: 运行中的进程遇到阻塞事件(I/O device operations)
处于运行状态的进程数量,最多等于CPU核心数(number of cores,有时候cores也称为processors)
In the malloc implement, we have a global variable header * lastFencepost
, what is the use for this variable.
global: 多个函数共享lastFencepost这个信息(allocate_object, coalesce)
检查sbrk()的新内存是否是连续: lastFencepost + sizeof(fencepost) = the_start_of_new_chunk
- 如果是连续,合并,合并过程中间的栅栏块会变成空闲内存的一部分,更新lastFencepost为新区域的最右端。
- 如果不是,更新lastFencepost为新区域最右端
int obj_can_be_expanded(size_t new_size, int *oldptr){
//返回0就是可以,返回1就是不行之类的,返回类型可以用int来代替bool
//ptr是指针,指向data开始的地方,所以是*ptr, 类型应该是整数指针
header *h = (header*)((char*)oldptr - ALLOCATE_HEADER_SIZE);//知道指向data的ptr,如何找h
header *rightheader = (header*)((char*)h + get_size(h));
size_t available = get_size(h) + get_size(rightheader) - ALLOCATE_HEDAER_SIZE;
if(get_state(rightheader) == UNALLOCATED && available >= new_size) {
return 0; //可以扩展
}
return 1;
}
int heap_free_count(size_t minSize, size_t maxSize) {
int count = 0;
for (i = 0; i < N_LIST; i++) {
header *freelist = &freelistSentinels[i]
header *cur = freelist->next;
while (cur != freelist) {
size_t t = get_size(curr)
if (size_t >= minSize && size_t <= maxSize){
count++;
}
cur = cur->next;
}
}
return count;
}
int pipe_open(char * command) {
int fd[2]; //定义一个长度为2的整数组,用于表示一个管道的两个端点,fd[0]是读端,fd[1]是写端
res = pipe(fd); //创建一个无名管道成功为0
if (res != 0) {
perror('pipe failed');
exit(1); //异常而退出
}
pid_t pid = fork(); // 0 是子进程
if (pid == 0) {
close(fd[0]);
dup2(fd[1], 1);//标准输出指向写端
char ** args = parseCmd(command);//两个星表示字符串
execvp(args[0], args);
// only something wrong
perror('execvp');
exit(1);
} else{
close(fd[1]);//otherwise, it will hang
return fd[0]
}
}
char ** parseCmd(char * command) {
int nargs = 0;
char ** args = malloc((strlen(command) + 1) * sizeof(char*));
char *s = strup(command);
char *p = s;
while (*p != '\0'){
while (*p == ''){
p++;
}
if (*p != '\0') {
args[nargs] = p;
nargs++;
while (*p != '\0' and *p != ' '){
p++;
}
if (*p == '\0'){
break
}
if (*p = ' '){
*p = '\0';//命令行中的end of word是'\0';
p++;
}
}
args[nargs] = NULL;
}
return args;
}
Enjoy Reading This Article?
Here are some more articles you might like to read next: