i386架构下load_arg函数中argc无法写入stack_top的调试求助
问题
在i386架构下实现了模拟load_arg的函数,使用VSCode调试时发现,函数倒数第三行的代码*(size_t*)stack_top = argc;执行后,argc的值并未存入*(size_t*)stack_top中,VSCode显示该值被“optimized out”。请问如何解决这个问题?或者说如何将argc的值正确写入*(size_t*)stack_top中?
uint32_t load_arg(PD *pgdir, char *const argv[]) { char *stack_top = (char*)vm_walk(pgdir, USR_MEM - PGSIZE, 7) + PGSIZE; size_t argv_va[MAX_ARGS_NUM + 1]; int argc; for (argc = 0; argv[argc]; ++argc) { assert(argc < MAX_ARGS_NUM); // push the string of argv[argc] to stack, record its va to argv_va[argc] stack_top -= (strlen(argv[argc])+1); strcpy(stack_top, argv[argc]); argv_va[argc] = USR_MEM - PGSIZE + ADDR2OFF(stack_top); } argv_va[argc] = 0; // set last argv NULL stack_top -= ADDR2OFF(stack_top) % 4; // align to 4 bytes for (int i = argc; i >= 0; --i) { // push the address of argv_va[argc] to stack to make argv array stack_top -= sizeof(size_t); *(size_t*)stack_top = argv_va[i]; } // push the address of the argv array as argument for _start stack_top -= sizeof(size_t); *(size_t*)stack_top = USR_MEM - PGSIZE + ADDR2OFF(stack_top); //push argc as argument for _start stack_top -= sizeof(size_t); *(size_t*)stack_top = argc; stack_top -= sizeof(size_t); // a hole for return value (useless but necessary) return USR_MEM - PGSIZE + ADDR2OFF(stack_top); }
解决方法
- 关闭编译器优化:调试阶段直接用
-O0编译选项,完全禁用优化。高优化级别(如-O2)下,编译器会认为*(size_t*)stack_top的写入没有被后续代码直接读取(函数返回的是地址而非该内存的值),从而将这个操作优化掉。在编译命令或Makefile中添加-O0,确保所有内存操作都被保留。 - 用
volatile标记指针:如果需要保留部分优化,可将stack_top声明为volatile char *stack_top,或者在写入时强制转换为volatile指针:*(volatile size_t*)stack_top = argc;。volatile会告知编译器该地址的内存是易变的,不能随意优化读写操作,保证写入动作被执行。 - 添加验证读取:在写入后增加一行读取代码,比如
volatile size_t check = *(size_t*)stack_top;,让编译器意识到这个写入有实际用途,避免被优化。不过这种方法属于临时 workaround,不如前两种规范。 - 检查地址计算宏:确认
ADDR2OFF宏的偏移计算是否正确,避免因地址错误导致写入的内存位置并非预期栈地址,看起来像是值没被写入。可验证USR_MEM - PGSIZE + ADDR2OFF(stack_top)是否对应stack_top的正确虚拟地址。
内容的提问来源于stack exchange,提问作者Peter Harry
相关产品推荐
相关产品推荐

