调用GetConsoleScreenBufferInfo返回异常值的问题排查与修复
问题原因与修复方法
核心原因
1. 参数传递方式错误
你大概率是用值传递来传递rows和columns参数。值传递时,函数内部修改的只是形参的副本,不会影响调用者的实参变量。所谓的“rows结果正确”只是巧合(比如实参初始值刚好匹配终端行数,或者栈上随机值碰巧符合),实际上rows也没有被函数正确修改;而columns的初始值是栈上的随机大值,所以显示异常。
2. 缺少必要头文件
如果getConsoleSize函数所在代码块未包含<sys/ioctl.h>和<unistd.h>,编译器会隐式声明struct winsize,导致结构体内存布局与实际不符。此时访问ws_col可能读取到错误的内存区域,产生随机值;而ws_row作为第一个成员,可能刚好能正确读取。
修复方案
方案一:使用指针传递参数
修改函数,让它接收int类型指针,直接修改调用者的变量:
#include <sys/ioctl.h> #include <unistd.h> #include <stdio.h> void getConsoleSize(int *rows, int *columns) { struct winsize w; // 处理ioctl调用失败的情况(比如非终端环境) if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == -1) { *rows = 24; *columns = 80; perror("获取终端尺寸失败"); return; } *rows = w.ws_row; *columns = w.ws_col; } int main() { int rows, columns; // 传递变量地址 getConsoleSize(&rows, &columns); printf("行数: %d, 列数: %d\n", rows, columns); return 0; }
方案二:返回结构体
定义包含行列数的结构体,让函数返回该结构体,避免指针传递:
#include <sys/ioctl.h> #include <unistd.h> #include <stdio.h> typedef struct { int rows; int columns; } ConsoleSize; ConsoleSize getConsoleSize() { ConsoleSize size = {24, 80}; // 设置默认值 struct winsize w; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) { size.rows = w.ws_row; size.columns = w.ws_col; } else { perror("获取终端尺寸失败"); } return size; } int main() { ConsoleSize size = getConsoleSize(); printf("行数: %d, 列数: %d\n", size.rows, size.columns); return 0; }
关键注意事项
- 确保所有使用
struct winsize的代码都包含<sys/ioctl.h>和<unistd.h>头文件,避免隐式声明导致的内存布局错误。 - 必须处理
ioctl调用失败的情况,比如程序在非终端环境运行时,设置合理的默认值或输出错误信息。
内容的提问来源于stack exchange,提问作者Skalmanen
相关产品推荐
相关产品推荐

