在C中,不能改变结构属性,除非使用#define VAL [英] In C, can't change a struct attribute except using #define val

查看:218
本文介绍了在C中,不能改变结构属性,除非使用#define VAL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Minix的3.1.2a我有一个结构 proc结构,其中存储的任何过程的PCB,
但我增加新的属性时,已经有问题 p_currenthash 在下面这个结构中的code。我无法改变它的价值除了利用的#define 指令定义的常数;否则,系统停止响应。为清楚起见这里是结构:

  proc结构{
  结构stackframe_s p_reg; / *进程的寄存器保存在栈帧* /#如果(CHIP == INTEL)
  reg_t p_ldt_sel; / *选择与LDT基址和限制GDT * /
  结构segdesc_s p_ldt [2 + NR_REMOTE_SEGS]; / * CS,DS和远程段* /
#万一#如果(CHIP == M68000)
/ * M68000的特定的寄存器和FPU详情,请点击这里。 * /
#万一  proc_nr_t p_nr; / *这个过程的数目(对于快速接入)* /
  结构私法* p_priv; / *系统权限结构* /
  短p_rts_flags; / *过程是可运行的只有零* /
  短p_misc_flags; / *标志是做暂停处理* /  焦炭p_priority; / *当前调度优先级* /
  焦炭p_max_priority; / *最大调度优先级* /
  焦炭p_ticks_left; / *调度的周期数左* /
  焦炭p_quantum_size; / *量子尺寸蜱* /  结构mem_map中p_memmap [NR_LOCAL_SEGS] / *内存映射(T,D,S)* /  clock_t表示p_user_time; / *用户时间刻度* /
  clock_t表示p_sys_time; / * SYS时间刻度* /  proc结构* p_nextready; / *指向下一个准备过程* /
  proc结构* p_caller_q; / *希望发送特效列表头* /
  proc结构* p_q_link; / *链接到下PROC希望发送* /
  消息* p_messbuf; / *指针传递消息缓冲区* /
  INT p_getfrom_e; / *从谁不希望过程接受? * /
  INT p_sendto_e; / *谁也处理要发送? * /  sigset_t p_pending; / *位图待处理内核信号* /  焦炭p_name [P_NAME_LEN] / *方法的名称,包括\\ 0 * /  INT p_endpoint; / *端点号,一代感知* /#如果DEBUG_SCHED_CHECK
  INT p_ready,p_found;
#万一  焦炭p_currenthash; / * *散列/};

现在,假设我要设置其值。起初,我使用下面定义的常量。

 的#define NONE -1注册proc结构* RP;RP-GT&; p_currenthash =无;

这工作得很好,但这: RP-GT&; p_currenthash = 0; 将导致程序停止响应

任何建议将AP preciated

下面是主初始化的main()

  / *启动球滚动。 * /
  结构BOOT_IMAGE * IP; / *启动映像指针* /
  注册proc结构* RP; / *过程指针* /
  注册结构私法* SP; / *特权结构指针* /
  注册INT I,S;
  INT hdrindex; / *指数的a.out头阵列* /
  phys_clicks TEXT_BASE;
  vir_clicks text_clicks,data_clicks;
  reg_t ktsb; / *内核任务堆栈基地* /
  结构EXEC e_hdr; / *为out的头部的拷贝* /  / *初始化中断控制器。 * /
  intr_init(1);  / *清除进程表。 Anounce每个插槽为空,设置映射
   *为proc_addr()和proc_nr()宏。做同样的表
   *作系统进程权限的结构。
   * /
  对(RP = BEG_PROC_ADDR,I = -NR_TASKS; RP< END_PROC_ADDR ++ RP,我++){
    RP-GT&; p_rts_flags = SLOT_FREE; / *初始化免费插槽* /
    RP-GT&; p_nr = I; / * PROC从PTR数* /    RP-GT&; p_currenthash =无;    RP-GT&; p_endpoint = _ENDPOINT(0,RP-GT&; p_nr); / *一代没有。 0 * /        (pproc_addr + NR_TASKS)[I] = RP; / * PROC从数PTR * /
  }
  对于(SP = BEG_PRIV_ADDR,I = 0;的sp LT; END_PRIV_ADDR ++ SP,我++){
    SP-GT&; s_proc_nr =无; / *初始化免费* /
    SP-GT&; S_ID = I; / *私法结构指数* /
    ppriv_addr [I] = SP; / *私法从数量PTR * /
  }  / *设置PROC表项为引导映像过程。的堆栈
   *内核任务被初始化为在数据空间阵列。书库
   的服务器*已被添加到由监视数据段,所以
   *堆栈指针被设置到数据段的结束。一切
   *过程是在低内存的8086在386只内核
   *在低内存,剩下的就是在扩展内存中加载。
   * /  / *任务堆栈。 * /
  ktsb =(reg_t)t_stack;  对于(i = 0; I< NR_BOOT_PROCS ++我){
    IP =&放大器;图片[I]; / *进程的属性* /
    RP = proc_addr(IP-> proc_nr); / *获取进程的指针* /
    IP->终点= RP-GT&; p_endpoint; / * IPC端点* /
    RP-GT&; p_max_priority = IP->优先; / *最大调度优先级* /
    RP-GT&; p_priority = IP->优先; / *当前优先* /
    RP-GT&; p_quantum_size = IP->量子; / *量子尺寸蜱* /
    RP-GT&; p_ticks_left = IP->量子; / *当前的信贷* /
    函数strncpy(RP-GT&; p_name,IP-> proc_name中,P_NAME_LEN); / *设置进程名* /
    (无效)get_priv(RP(IP->旗帜与放大器; SYS_PROC)); / *分配结构* /
    私法(RP) - GT; s_flags = IP->标志; / *进程标志* /
    私法(RP) - GT; s_trap_mask = IP-> trap_mask; / *允许的陷阱* /
    私法(RP) - GT; s_call_mask = IP-> call_mask; / *内核调用面具* /
    PRIV(RP) - > s_ipc_to.chunk [0] = IP-> ipc_to; / *限制目标* /
    如果(iskerneln(proc_nr(RP))){/ *内核的一部分? * /
        如果(IP-> stksize大于0){/ *硬件堆栈大小为0 * /
            RP-GT&;&p_priv- GT; s_stack_guard =(reg_t *)ktsb;
            * RP-GT&;&p_priv- GT; s_stack_guard = STACK_GUARD;
        }
        ktsb + = IP-> stksize; / *指向堆栈的高端* /
        RP-GT&; p_reg.sp = ktsb; / *这个任务的初始堆栈PTR * /
        TEXT_BASE = kinfo code_base方式>> CLICK_SHIFT;
                    / *过程是在内核* /
        hdrindex = 0; / *所有使用第一个a.out头部* /
    }其他{
        hdrindex = 1 + I-NR_TASKS; / *服务器,驱动程序,INIT * /
    }    / *引导加载程序创建的a.out的头的数组在
     *绝对地址AOUT。获取一个元素e_hdr。
     * /
    phys_copy(AOUT + hdrindex * A_MINHDR,vir2phys(安培; e_hdr)
                        (phys_bytes)A_MINHDR);
    / *转换地址的点击和建设进程的内存映射* /
    TEXT_BASE = e_hdr.a_syms>> CLICK_SHIFT;
    text_clicks =(e_hdr.a_text + CLICK_SIZE-1)GT;> CLICK_SHIFT;
    如果((e_hdr.a_flags&放大器;!A_SEP))text_clicks = 0; / *通用的I和D * /
    data_clicks =(e_hdr.a_total + CLICK_SIZE-1)GT;> CLICK_SHIFT;
    RP-GT&; p_memmap [T] .mem_phys = TEXT_BASE;
    RP-GT&; p_memmap [T] .mem_len = text_clicks;
    RP-GT&; p_memmap研究[D] .mem_phys = TEXT_BASE + text_clicks;
    RP-GT&; p_memmap研究[D] .mem_len = data_clicks;
    RP-GT&; p_memmap [S] .mem_phys = TEXT_BASE + text_clicks + data_clicks;
    RP-GT&; p_memmap [S] .mem_vir = data_clicks; / *空 - 堆栈数据* /    / *设置初始寄存器值。对于任务的处理器状态字
     *是来自其他进程的不同,因为任务可以
     *访问I / O;这是不允许的,以较低权限的进程
     * /
    RP-GT&; p_reg.pc =(reg_t)IP-GT&; initial_pc;
    RP-GT&; p_reg.psw =(iskernelp(RP))? INIT_TASK_PSW:INIT_PSW;    / *初始化服务器堆栈指针。把它记下来一个字
     *给crtso.s的东西为ARGC来使用。
     * /
    如果(isusern(proc_nr(RP))){/ *用户空间进程? * /
        RP-GT&; p_reg.sp =(RP-GT&; p_memmap [S] .mem_vir +
                RP-GT&; p_memmap [S] .mem_len)LT;< CLICK_SHIFT;
        RP-GT&; p_reg.sp - = sizeof的(reg_t);
    }    / *设置就绪。硬件任务是从来没有准备好。 * /
    如果(RP-GT&; p_nr =硬件!){
        RP-> p_rts_flags = 0; / *可运行的,如果没有标志* /
        lock_enqueue(RP); / *添加到调度的队列* /
    }其他{
        RP-GT&; p_rts_flags = NO_MAP;从运行/ * prevent * /
    }    / * code和数据段必须在保护模式下进行分配。 * /
    alloc_segments(RP);
  }


解决方案

 注册proc结构* RP;RP-GT&; p_currenthash =无;

RP 是一个未初始化的指针;它不是指向一个有效的 proc结构对象,所以取消引用它导致的未定义行为的。即当分配给这没有崩溃的事实是-1运气纯正。 (运气不好,因为它误导了你要相信你在做一些有意义的事情)

In Minix 3.1.2a I've a struct "struct proc" where the PCB of any process stored, but I've a problem when adding new attribute "p_currenthash" in the code below to this struct. I can't change its value except using a constant defined by #define directive; otherwise, the system stops responding. For clarity here is the structure:

struct proc {
  struct stackframe_s p_reg;    /* process' registers saved in stack frame */

#if (CHIP == INTEL)
  reg_t p_ldt_sel;      /* selector in gdt with ldt base and limit */
  struct segdesc_s p_ldt[2+NR_REMOTE_SEGS]; /* CS, DS and remote segments */
#endif 

#if (CHIP == M68000)
/* M68000 specific registers and FPU details go here. */
#endif 

  proc_nr_t p_nr;       /* number of this process (for fast access) */
  struct priv *p_priv;      /* system privileges structure */
  short p_rts_flags;        /* process is runnable only if zero */
  short p_misc_flags;       /* flags that do suspend the process */

  char p_priority;      /* current scheduling priority */
  char p_max_priority;      /* maximum scheduling priority */
  char p_ticks_left;        /* number of scheduling ticks left */
  char p_quantum_size;      /* quantum size in ticks */

  struct mem_map p_memmap[NR_LOCAL_SEGS];   /* memory map (T, D, S) */

  clock_t p_user_time;      /* user time in ticks */
  clock_t p_sys_time;       /* sys time in ticks */

  struct proc *p_nextready; /* pointer to next ready process */
  struct proc *p_caller_q;  /* head of list of procs wishing to send */
  struct proc *p_q_link;    /* link to next proc wishing to send */
  message *p_messbuf;       /* pointer to passed message buffer */
  int p_getfrom_e;      /* from whom does process want to receive? */
  int p_sendto_e;       /* to whom does process want to send? */

  sigset_t p_pending;       /* bit map for pending kernel signals */



  char p_name[P_NAME_LEN];  /* name of the process, including \0 */

  int p_endpoint;       /* endpoint number, generation-aware */

#if DEBUG_SCHED_CHECK
  int p_ready, p_found;
#endif

  char p_currenthash; /* hash */

};

Now, suppose I want to set its value. Initially I use the constant defined below.

#define NONE -1

register struct proc *rp;

rp->p_currenthash=NONE;

That works fine, but this: rp->p_currenthash=0 ; will cause the program to stop responding.

Any suggestions will be appreciated

Here's the main initialization in main():

/* Start the ball rolling. */
  struct boot_image *ip;    /* boot image pointer */
  register struct proc *rp; /* process pointer */
  register struct priv *sp; /* privilege structure pointer */
  register int i, s;
  int hdrindex;         /* index to array of a.out headers */
  phys_clicks text_base;
  vir_clicks text_clicks, data_clicks;
  reg_t ktsb;           /* kernel task stack base */
  struct exec e_hdr;        /* for a copy of an a.out header */

  /* Initialize the interrupt controller. */
  intr_init(1);

  /* Clear the process table. Anounce each slot as empty and set up mappings 
   * for proc_addr() and proc_nr() macros. Do the same for the table with 
   * privilege structures for the system processes. 
   */
  for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) {
    rp->p_rts_flags = SLOT_FREE;        /* initialize free slot */
    rp->p_nr = i;               /* proc number from ptr */

    rp->p_currenthash=NONE;

    rp->p_endpoint = _ENDPOINT(0, rp->p_nr); /* generation no. 0 */

        (pproc_addr + NR_TASKS)[i] = rp;        /* proc ptr from number */
  }
  for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) {
    sp->s_proc_nr = NONE;           /* initialize as free */
    sp->s_id = i;               /* priv structure index */
    ppriv_addr[i] = sp;         /* priv ptr from number */
  }

  /* Set up proc table entries for processes in boot image.  The stacks of the
   * kernel tasks are initialized to an array in data space.  The stacks
   * of the servers have been added to the data segment by the monitor, so
   * the stack pointer is set to the end of the data segment.  All the
   * processes are in low memory on the 8086.  On the 386 only the kernel
   * is in low memory, the rest is loaded in extended memory.
   */

  /* Task stacks. */
  ktsb = (reg_t) t_stack;

  for (i=0; i < NR_BOOT_PROCS; ++i) {
    ip = &image[i];             /* process' attributes */
    rp = proc_addr(ip->proc_nr);        /* get process pointer */
    ip->endpoint = rp->p_endpoint;      /* ipc endpoint */
    rp->p_max_priority = ip->priority;  /* max scheduling priority */
    rp->p_priority = ip->priority;      /* current priority */
    rp->p_quantum_size = ip->quantum;   /* quantum size in ticks */
    rp->p_ticks_left = ip->quantum;     /* current credit */
    strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set process name */
    (void) get_priv(rp, (ip->flags & SYS_PROC));    /* assign structure */
    priv(rp)->s_flags = ip->flags;          /* process flags */
    priv(rp)->s_trap_mask = ip->trap_mask;      /* allowed traps */
    priv(rp)->s_call_mask = ip->call_mask;      /* kernel call mask */
    priv(rp)->s_ipc_to.chunk[0] = ip->ipc_to;   /* restrict targets */
    if (iskerneln(proc_nr(rp))) {       /* part of the kernel? */ 
        if (ip->stksize > 0) {      /* HARDWARE stack size is 0 */
            rp->p_priv->s_stack_guard = (reg_t *) ktsb;
            *rp->p_priv->s_stack_guard = STACK_GUARD;
        }
        ktsb += ip->stksize;    /* point to high end of stack */
        rp->p_reg.sp = ktsb;    /* this task's initial stack ptr */
        text_base = kinfo.code_base >> CLICK_SHIFT;
                    /* processes that are in the kernel */
        hdrindex = 0;       /* all use the first a.out header */
    } else {
        hdrindex = 1 + i-NR_TASKS;  /* servers, drivers, INIT */
    }

    /* The bootstrap loader created an array of the a.out headers at
     * absolute address 'aout'. Get one element to e_hdr.
     */
    phys_copy(aout + hdrindex * A_MINHDR, vir2phys(&e_hdr),
                        (phys_bytes) A_MINHDR);
    /* Convert addresses to clicks and build process memory map */
    text_base = e_hdr.a_syms >> CLICK_SHIFT;
    text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT;
    if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0;     /* common I&D */
    data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT;
    rp->p_memmap[T].mem_phys = text_base;
    rp->p_memmap[T].mem_len  = text_clicks;
    rp->p_memmap[D].mem_phys = text_base + text_clicks;
    rp->p_memmap[D].mem_len  = data_clicks;
    rp->p_memmap[S].mem_phys = text_base + text_clicks + data_clicks;
    rp->p_memmap[S].mem_vir  = data_clicks; /* empty - stack is in data */

    /* Set initial register values.  The processor status word for tasks 
     * is different from that of other processes because tasks can
     * access I/O; this is not allowed to less-privileged processes 
     */
    rp->p_reg.pc = (reg_t) ip->initial_pc;
    rp->p_reg.psw = (iskernelp(rp)) ? INIT_TASK_PSW : INIT_PSW;

    /* Initialize the server stack pointer. Take it down one word
     * to give crtso.s something to use as "argc".
     */
    if (isusern(proc_nr(rp))) {     /* user-space process? */ 
        rp->p_reg.sp = (rp->p_memmap[S].mem_vir +
                rp->p_memmap[S].mem_len) << CLICK_SHIFT;
        rp->p_reg.sp -= sizeof(reg_t);
    }

    /* Set ready. The HARDWARE task is never ready. */
    if (rp->p_nr != HARDWARE) {
        rp->p_rts_flags = 0;        /* runnable if no flags */
        lock_enqueue(rp);       /* add to scheduling queues */
    } else {
        rp->p_rts_flags = NO_MAP;   /* prevent from running */
    }

    /* Code and data segments must be allocated in protected mode. */
    alloc_segments(rp);
  }

解决方案

register struct proc *rp;

rp->p_currenthash=NONE;

rp is an uninitialized pointer; it isn't pointing to a valid struct proc object, and so dereferencing it leads to undefined behavior. The fact that this didn't crash when assigning -1 was pure luck. (bad luck, because it misled you to believe you were doing something meaningful)

这篇关于在C中,不能改变结构属性,除非使用#define VAL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆