使用 Win32 读取文件时 glShaderSource 访问冲突
glShaderSource access violation when using Win32 to read files
因此,我正在尝试仅使用 Win32 API 和 OpenGL 来设置基本的 OpenGL 场景,但是我在加载着色器和 glShaderSource 函数方面遇到了很大的问题。我正在这样阅读我的文件:
//HEADER
class FileReader
{
public:
FileReader(const LPCSTR FileName);
const void* GetFileData();
~FileReader();
private:
HANDLE FileHandle;
void* FileDataMemory;
};
//ACTUAL CODE
FileReader::FileReader(const LPCSTR FileName)
{
FileHandle = CreateFileA(FileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (FileHandle == INVALID_HANDLE_VALUE)
{
OutputDebugStringA("Failed to open file ");
OutputDebugStringA(FileName);
OutputDebugStringA(" for reading, application could not be loaded\n");
ExitProcess(-2);
}
unsigned int FileSize = GetFileSize(FileHandle, 0);
DWORD BytesRead;
FileDataMemory = VirtualAlloc(0, FileSize, MEM_COMMIT, PAGE_READWRITE);
ReadFile(FileHandle, FileDataMemory, FileSize, &BytesRead, 0);
if (BytesRead < FileSize)
{
OutputDebugStringA("File was not read completely\n");
}
}
const void* FileReader::GetFileData()
{
return FileDataMemory;
}
FileReader::~FileReader()
{
CloseHandle(FileHandle);
}
然后我使用这个 class 从磁盘加载顶点着色器,如下所示:
VertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(VertexShader, 1, static_cast<const GLchar* const*>(VertexShaderFile->GetFileData()), 0);
但是我的应用程序在 glShaderSource 上给了我一个读取地址 0xFFFFFFFF 的访问冲突。我只是很困惑,因为当我尝试在调试模式下查看这块内存时,它看起来很正常并且里面有正确的数据,所以我不知道该怎么做。
从文件中读取的着色器源代码字符串不是0终止的。
预留 FileSize+1
字节内存,并确保缓冲区的最后一个字节为 0。例如:
FileDataMemory = VirtualAlloc(0, FileSize+1, MEM_COMMIT, PAGE_READWRITE);
ZeroMemory(FileDataMemory, FileSize+1);
ReadFile(FileHandle, FileDataMemory, FileSize, &BytesRead, 0);
此外,glShaderSource
的第三个参数是一个字符串数组 (const GLchar **
):
const GLchar *source = static_cast<const GLchar*>(VertexShaderFile->GetFileData());
glShaderSource(VertexShader, 1, &source, 0);
您在代码中实际做的是转换 VertexShaderFile->GetFileData()
。你需要做的就是施放 &VertexShaderFile->GetFileData()
此外,我推荐使用STL来读取shader源文件。例如:
std::ifstream sourceFile(FileName, std::fstream::in);
std::string sourceCode = std::string(
std::istreambuf_iterator<char>(sourceFile),
std::istreambuf_iterator<char>());
因此,我正在尝试仅使用 Win32 API 和 OpenGL 来设置基本的 OpenGL 场景,但是我在加载着色器和 glShaderSource 函数方面遇到了很大的问题。我正在这样阅读我的文件:
//HEADER
class FileReader
{
public:
FileReader(const LPCSTR FileName);
const void* GetFileData();
~FileReader();
private:
HANDLE FileHandle;
void* FileDataMemory;
};
//ACTUAL CODE
FileReader::FileReader(const LPCSTR FileName)
{
FileHandle = CreateFileA(FileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (FileHandle == INVALID_HANDLE_VALUE)
{
OutputDebugStringA("Failed to open file ");
OutputDebugStringA(FileName);
OutputDebugStringA(" for reading, application could not be loaded\n");
ExitProcess(-2);
}
unsigned int FileSize = GetFileSize(FileHandle, 0);
DWORD BytesRead;
FileDataMemory = VirtualAlloc(0, FileSize, MEM_COMMIT, PAGE_READWRITE);
ReadFile(FileHandle, FileDataMemory, FileSize, &BytesRead, 0);
if (BytesRead < FileSize)
{
OutputDebugStringA("File was not read completely\n");
}
}
const void* FileReader::GetFileData()
{
return FileDataMemory;
}
FileReader::~FileReader()
{
CloseHandle(FileHandle);
}
然后我使用这个 class 从磁盘加载顶点着色器,如下所示:
VertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(VertexShader, 1, static_cast<const GLchar* const*>(VertexShaderFile->GetFileData()), 0);
但是我的应用程序在 glShaderSource 上给了我一个读取地址 0xFFFFFFFF 的访问冲突。我只是很困惑,因为当我尝试在调试模式下查看这块内存时,它看起来很正常并且里面有正确的数据,所以我不知道该怎么做。
从文件中读取的着色器源代码字符串不是0终止的。
预留 FileSize+1
字节内存,并确保缓冲区的最后一个字节为 0。例如:
FileDataMemory = VirtualAlloc(0, FileSize+1, MEM_COMMIT, PAGE_READWRITE);
ZeroMemory(FileDataMemory, FileSize+1);
ReadFile(FileHandle, FileDataMemory, FileSize, &BytesRead, 0);
此外,glShaderSource
的第三个参数是一个字符串数组 (const GLchar **
):
const GLchar *source = static_cast<const GLchar*>(VertexShaderFile->GetFileData());
glShaderSource(VertexShader, 1, &source, 0);
您在代码中实际做的是转换 VertexShaderFile->GetFileData()
。你需要做的就是施放 &VertexShaderFile->GetFileData()
此外,我推荐使用STL来读取shader源文件。例如:
std::ifstream sourceFile(FileName, std::fstream::in);
std::string sourceCode = std::string(
std::istreambuf_iterator<char>(sourceFile),
std::istreambuf_iterator<char>());