【问题标题】:Why is the pointer changing for no reason?为什么指针会无缘无故地改变?
【发布时间】:2017-01-10 03:30:51
【问题描述】:

我正在处理ops-class 的作业 2。

以下函数为正在创建的进程引导一个文件处理程序数组(例如,提供的测试程序的用户进程here)。

int _fh_bootstrap(struct fharray *fhs){

/* Initialize the file handle array of this process */
fharray_init(fhs);

/* String variables initialized for passage to vfs_open */
char* console_inp = kstrdup(CONSOLE); // CONSOLE = "con:"
char* console_out = kstrdup(console_inp);
char* console_err = kstrdup(console_inp);

/* Return variable */
int ret = 0;

/* Initialize the console files STDIN, STDOUT and STDERR */
struct vnode *stdin;
ret = vfs_open(console_inp,O_RDONLY,0,&stdin);
if(ret != 0){
    return ret;
}
kfree(console_inp);

struct fh *stdinfh = kmalloc(sizeof(struct fh));
ret =  _fh_create(O_RDONLY,stdin,stdinfh);
if(ret != 0){
    return ret;
}

stdinfh->fd = STDIN_FILENO;
fharray_add(fhs,stdinfh,NULL);

struct vnode *stdout;
ret = vfs_open(console_out,O_WRONLY,0,&stdout);
if(ret != 0){
    return ret;
}
kfree(console_out);

struct fh *stdoutfh = kmalloc(sizeof(struct fh));
ret =  _fh_create(O_WRONLY,stdout,stdoutfh);
if(ret != 0){
    return ret;
}

stdoutfh->fd = STDOUT_FILENO;
fharray_add(fhs,stdoutfh,NULL);

struct vnode *stderr;
ret = vfs_open(console_err,O_WRONLY,0,&stderr);
if(ret != 0){
    return ret;
}
kfree(console_err);

struct fh *stderrfh = kmalloc(sizeof(struct fh));
ret =  _fh_create(O_WRONLY,stderr,stderrfh);
if(ret != 0){
    return ret;
}

stderrfh->fd = STDERR_FILENO;
fharray_add(fhs,stderrfh,NULL);

fharray_setsize(fhs,MAX_FD);    

return 0;

/* Initialization of stdin, out and err filehandlers complete */
}

如果我使用 os161-gdb 单步执行此函数,我会注意到以下内容:

//*stdinfh after the call to _fh_create 
{fd = 0, flag = 0, fh_seek = 0, fh_vnode = 0x80044ddc}

//**stdinfh->fh_vnode
{vn_refcount = 2, vn_countlock = {splk_lock = 0, splk_holder = 0x0}, vn_fs = 0x0,
vn_data = 0x8004ab60, vn_ops = 0x8003e690 <dev_vnode_ops>}

这是奇怪的部分。在单步执行对 kmalloc 的第二次调用(初始化 stdoutfh)之后,stdinfh->fh_vnode 指针改变了值!

//**stdinfh->fh_vnode
(struct vnode *) 0x1

更奇怪的是,在继续下一行之后

fharray_add(fhs,stdoutfh,NULL);

*stdoutfh->fh_vnode 和 *stdinfh->fh_vnode 的值是一样的

1 可能的解释:操作系统是否没有足够的堆内存。我发现这不太可能,即使假设了这一点,我也无法准确解释这里发生了什么。

一些额外的代码

  1. _fh_create
  2. 结构体定义

    static int _fh_create(int flag, struct vnode *file, struct fh *handle){
    
    KASSERT(file != NULL);
    
    /* W , R , RW */
    if ( 
        ((flag & O_RDONLY) && (flag & O_WRONLY)) ||
        ((flag & O_RDWR) && ((flag & O_RDONLY) || (flag & O_WRONLY)))
    ) {
        handle = NULL;
        return 1;
    }
    
    handle->flag = flag;
    handle->fh_seek = 0;
    handle->fh_vnode = &file;
    
    return 0;
    }
    

    struct fh { uint32_t fd; // file descriptor int flag; // File handler mode off_t fh_seek; // seek position in file struct vnode **fh_vnode; // File object of the file }

struct vnode的定义见here

如果您需要更多信息,请告诉我,感谢您的帮助!

【问题讨论】:

  • handle-&gt;fh_vnode = &amp;file; 在函数返回时将是一个悬空指针。函数参数是自动变量(堆栈)
  • 您对已更改节点值的 gdb 引用给出了错误的类型 -- * 而不是 **。这是错字还是您最近更改了类型?
  • @M.M 所以我不确定我是否完全理解你的观点。您的意思是说在 _fh_create 的堆栈框架内创建了一个新变量,并在函数返回后删除了该变量?值 *stdoutfh->fh_vnode 和 *stdinfh->fh_vnode 最终是相同的,因为它们指向临时堆栈帧 (_fh_create) 的相同偏移量?
  • @Deepak 是的,差不多就是这样
  • @M.M 嗯,我想过这个,但我不记得为什么我没有做出适当的改变。我应该如何改变我的功能来解决这个“副作用”?

标签: c os161


【解决方案1】:

代码handle-&gt;fh_vnode 设置了一个指向自动变量的指针(“在堆栈上”),函数参数是自动变量。函数返回后,这将是一个悬空指针。

要解决此问题,您需要重新设计代码,例如也许struct fh 应该只存储file 而不是指向file 的指针。

【讨论】:

    猜你喜欢
    • 2019-06-24
    • 2018-04-09
    • 1970-01-01
    • 1970-01-01
    • 2012-04-16
    • 2018-10-23
    • 1970-01-01
    • 2019-03-16
    • 2011-12-19
    相关资源
    最近更新 更多