使用strncat编写GLFW着色器加载函数返回垃圾值是什么原因
代码问题分析
- 野指针与内存未分配
你声明的char* realShader没有初始化,也没有申请任何堆内存空间,直接调用strncat向其写入内容属于非法内存访问,指针指向的随机内存中原有的垃圾数据就是你输出中乱码前缀的来源,该行为属于未定义行为,严重时会直接触发程序崩溃。
- 野指针与内存未分配
strncat使用不符合要求strncat要求目标参数必须是已存在的、以\0结尾的合法C字符串,未初始化的realShader不满足该条件,拼接逻辑本身就是错误的。同时用strncat逐字符拼接的效率极低,完全不适合该场景。
- 文件操作未做合法性校验
调用fopen打开文件后没有判断返回值是否为NULL,如果文件不存在、路径错误或者没有读取权限,后续的fgetc操作会直接传入空指针触发崩溃。
- 文件操作未做合法性校验
- 字符串缺少结束符
C语言中字符串必须以\0作为结束标志,你读完所有文件内容后没有手动追加\0,printf输出时会一直向后读取内存直到遇到随机的\0为止,就会出现多余的乱码后缀。
- 字符串缺少结束符
fgetc返回值接收类型错误fgetc的返回值为int类型,EOF本质是值为-1的int常量,如果你使用char类型接收返回值,在char为无符号类型的系统中,永远不可能等于EOF,会造成死循环。
修复后代码示例
#include <stdio.h> #include <stdlib.h> #include <string.h> char* loadShader(const char* shaderName){ // 打开文件并校验 FILE *shader = fopen(shaderName, "r"); if (shader == NULL) { perror("打开文件失败"); return NULL; } // 先获取文件大小 fseek(shader, 0, SEEK_END); long fileSize = ftell(shader); rewind(shader); // 分配内存:文件大小+1存结束符 char* realShader = (char*)malloc(fileSize + 1); if (realShader == NULL) { perror("内存分配失败"); fclose(shader); return NULL; } // 一次性读取全部内容 size_t readSize = fread(realShader, 1, fileSize, shader); if (readSize != fileSize) { perror("读取文件失败"); free(realShader); fclose(shader); return NULL; } // 加字符串结束符 realShader[fileSize] = '\0'; fclose(shader); return realShader; } int main(void){ char* filename = "default"; char* shader = loadShader(filename); if (shader != NULL) { printf("%s\n", shader); // 用完记得释放堆内存,避免内存泄漏 free(shader); } return 0; }
内容的提问来源于stack exchange,提问作者The Parallax
相关产品推荐
相关产品推荐

