GLFW窗口指针0xCCCCCCCC访问违例问题求助
解决你的GLFW DLL内存访问违例问题
嘿,我一眼就揪出了导致你遇到read access violation. window was 0xCCCCCCCC错误的两个核心问题,咱们一步步来修复:
问题1:返回局部变量地址,直接生成野指针
你在LIB_CreateWindow里定义了栈上的局部变量LIB_Window wind;,函数执行完毕后,栈上的这个变量会被系统回收,内存会被标记成0xCCCCCCCC(这是VC++用来标记已释放栈内存的特殊值)。当你返回&wind;给调用者时,拿到的就是一个指向无效内存的野指针,后续任何访问这个指针的操作都会触发内存错误。
问题2:画蛇添足的二级指针
你的LIB_Window结构体里用了GLFWwindow** window;,但glfwCreateWindow返回的本来就是GLFWwindow*类型的一级指针,强行转成二级指针完全没必要,这会导致后续调用GLFW API时指针类型不匹配,雪上加霜。
修复步骤全解析
1. 先修正结构体的指针类型
把LIB_Window里的二级指针改成一级指针,和GLFW的返回类型匹配:
struct LIB_Window { LIB_String title; int x; int y; int width; int height; LIB_Bool fullscreen; GLFWwindow* window; // 改为一级指针 };
2. 用堆内存创建窗口实例
把局部变量换成malloc分配的堆内存,这样函数结束后内存不会被回收:
LIB_Window* LIB_CreateWindow(const LIB_String title, int x, int y, const int width, const int height, const LIB_Bool resizable, const LIB_Bool fullscreen) { // 堆内存分配,确保内存持久化 LIB_Window* wind = (LIB_Window*)malloc(sizeof(LIB_Window)); if (!wind) { glfwTerminate(); return NULL; } wind->title = title; if (x == LIB_CENTER_POSITION) { const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); x = (mode->width - width) / 2; } wind->x = x; if (y == LIB_CENTER_POSITION) { const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); y = (mode->height - height) / 2; } wind->y = y; wind->width = width; wind->height = height; wind->fullscreen = fullscreen; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); glfwWindowHint(GLFW_RESIZABLE, resizable); // 直接用一级指针接收glfwCreateWindow的返回值 wind->window = NULL; if (fullscreen == 1) { wind->window = glfwCreateWindow(width, height, title, glfwGetPrimaryMonitor(), NULL); } else { wind->window = glfwCreateWindow(width, height, title, NULL, NULL); } // 窗口创建失败时要释放已分配的内存 if (!wind->window) { glfwTerminate(); free(wind); return NULL; } glfwSetWindowPos(wind->window, x, y); int screen_width, screen_height; glfwGetFramebufferSize(wind->window, &screen_width, &screen_height); glfwMakeContextCurrent(wind->window); glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { glfwDestroyWindow(wind->window); free(wind); return NULL; } glViewport(0, 0, screen_width, screen_height); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glEnable(GL_BLEND); glEnable(GL_ALPHA_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); return wind; }
3. 修正所有GLFW API调用的指针
把所有((GLFWwindow*)window->window)的多余强制转换去掉,直接用window->window就行,比如:
void LIB_SwapWindowBuffers(LIB_Window * window) { glfwSwapBuffers(window->window); } LIB_Bool LIB_IsWindowOpened(LIB_Window * window) { return !glfwWindowShouldClose(window->window); }
4. 完善窗口销毁函数
原来的LIB_DestroyWindow没有销毁GLFW窗口,要加上glfwDestroyWindow,同时确保内存释放:
void LIB_DestroyWindow(LIB_Window * window) { if (window && window->window) { glfwDestroyWindow(window->window); } free(window); }
额外提醒
- 一定要记得调用
LIB_DestroyWindow来释放堆内存,不然会造成内存泄漏 - 如果你的DLL和调用程序用了不同的C运行时库(CRT),可能会出现跨模块内存分配/释放的问题,建议在VS项目设置里把CRT统一设为
Multi-threaded DLL (/MD) - 所有涉及GLFW窗口的操作,最好先检查
window->window不为NULL再执行,避免空指针错误
内容的提问来源于stack exchange,提问作者Ruks
相关产品推荐
相关产品推荐

