PE File Buffer and Memory Buffer

本文详细介绍了一种从文件读取PE(Portable Executable)格式数据到内存,并将内存中的PE数据转换回文件的方法。首先,通过使用标准C库函数如fopen、fseek、fread等读取文件到内存缓冲区。接着,解析PE文件头,获取各段信息,按需分配内存并填充数据。最后,将内存中的PE数据转换为文件保存。
// FileMemBufferTest.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include "pch.h"
#include <iostream>
#include <Windows.h>

/*
* 获取文件路径
*/
void GetFile(TCHAR* szPath)
{
#if 1
    if (!GetModuleFileName(NULL, szPath, MAX_PATH))
    {
        printf("Cannot install service (%d)\n", GetLastError());
        return;
    }
    char* pPathEnd = (char*)szPath + strlen(szPath);
    while (pPathEnd--)
    {
        if (*pPathEnd == '\\')
        {
            *pPathEnd = '\0';
            break;
        }
    }
    // user32test.dll ntoskrnltest.exe
    //strcat_s(szPath, "\\ntdlltest.dll");

    // special? ntoskrnltest.exe
    strcat_s(szPath, MAX_PATH, "\\MyPE.exe");
#else
    strcpy_s(szPath, "D:\\test.dll");
#endif
}

/*
* 读取文件到内存
*/
bool ReadFile(const char* name, char** p)
{
    bool bRet = false;

    FILE* fp = NULL;
    errno_t error = fopen_s(&fp, name, "rb");
    if (error == 0)
    {
        fseek(fp, 0, SEEK_END);
        DWORD bytes = ftell(fp);
        // do not forget to free memory later
        *p = (char*)malloc(bytes);

        fseek(fp, 0, SEEK_SET);
        fread_s(*p, bytes, sizeof(char), bytes, fp);

        fclose(fp);
        bRet = true;
    }
    else
    {
        printf("ReadFile %s error %d\n", name, error);
    }

    return bRet;
}

BYTE* FileToMemory(BYTE* fileBuffer)
{
    PIMAGE_DOS_HEADER pDosHeader;
    PIMAGE_NT_HEADERS32 pNTHeaders;
    PIMAGE_SECTION_HEADER pSectionHeader;

    pDosHeader = (PIMAGE_DOS_HEADER)fileBuffer;
    pNTHeaders = (PIMAGE_NT_HEADERS32)(fileBuffer + pDosHeader->e_lfanew);
    pSectionHeader = (PIMAGE_SECTION_HEADER)((char*)pNTHeaders + sizeof(IMAGE_NT_HEADERS32));

    // get image size
    int sizeOfImage = pNTHeaders->OptionalHeader.SizeOfImage;
    // allocate memory
    BYTE* memBuffer = new BYTE[sizeOfImage];
    // zero memory
    memset(memBuffer, 0, sizeOfImage);

    int sizeOfFileHead = 0;
    sizeOfFileHead += pDosHeader->e_lfanew;
    sizeOfFileHead += sizeof(IMAGE_NT_HEADERS32);
    sizeOfFileHead += sizeof(IMAGE_SECTION_HEADER) * pNTHeaders->FileHeader.NumberOfSections;

    // copy header from file buffer
    memcpy_s(memBuffer, sizeOfFileHead, fileBuffer, sizeOfFileHead);

    char* Name[IMAGE_SIZEOF_SHORT_NAME + 1] = { 0 };
    int sectionNum = pNTHeaders->FileHeader.NumberOfSections;
    for (int i = 0; i < sectionNum; i++)
    {
        memcpy_s(Name, IMAGE_SIZEOF_SHORT_NAME, pSectionHeader->Name, IMAGE_SIZEOF_SHORT_NAME);
        printf("%d %s\nVirtualAddress: %08X, VirtualSize: %08X ==> %08X\nPointerToRawData: %08X, SizeOfRawData: %08X ==> %08X\n",
            i, Name,
            pSectionHeader->VirtualAddress,
            pSectionHeader->Misc.VirtualSize,
            pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize,
            pSectionHeader->PointerToRawData,
            pSectionHeader->SizeOfRawData,
            pSectionHeader->PointerToRawData + pSectionHeader->SizeOfRawData
        );

        if (pSectionHeader->SizeOfRawData == 0)
        {
            // fill with zero
            pSectionHeader->VirtualAddress;
            pSectionHeader->Misc.VirtualSize;
        }
        else
        {
            // memory -> VirtualSize
            int dataLen = pSectionHeader->SizeOfRawData > pSectionHeader->Misc.VirtualSize ? pSectionHeader->Misc.VirtualSize : pSectionHeader->SizeOfRawData;
            char* dest = (char*)(memBuffer + pSectionHeader->VirtualAddress);
            char* src = (char*)(fileBuffer + pSectionHeader->PointerToRawData);
            memcpy_s(dest, pSectionHeader->Misc.VirtualSize, src, dataLen);
        }

        pSectionHeader++;
    }

    // release heap memory later
    return memBuffer;
}

BYTE* MemoryToFile(BYTE* memBuffer, DWORD& sizeOfPERawData)
{
    PIMAGE_DOS_HEADER pDosHeader;
    PIMAGE_NT_HEADERS32 pNTHeaders;
    PIMAGE_SECTION_HEADER pSectionHeader;

    pDosHeader = (PIMAGE_DOS_HEADER)memBuffer;
    pNTHeaders = (PIMAGE_NT_HEADERS32)(memBuffer + pDosHeader->e_lfanew);
    pSectionHeader = (PIMAGE_SECTION_HEADER)((char*)pNTHeaders + sizeof(IMAGE_NT_HEADERS32));

    // get image size
    int sizeOfImage = pNTHeaders->OptionalHeader.SizeOfImage;
    
    int sizeOfFileHead = 0;
    sizeOfFileHead += pDosHeader->e_lfanew;
    sizeOfFileHead += sizeof(IMAGE_NT_HEADERS32);
    sizeOfFileHead += sizeof(IMAGE_SECTION_HEADER) * pNTHeaders->FileHeader.NumberOfSections;

    // create new file buffer
    BYTE* newFileBuffer = new BYTE[sizeOfImage];
    memset(newFileBuffer, 0, sizeOfImage);

    memcpy_s(newFileBuffer, sizeOfFileHead, memBuffer, sizeOfFileHead);

    pSectionHeader = (PIMAGE_SECTION_HEADER)((char*)pNTHeaders + sizeof(IMAGE_NT_HEADERS32));
    char Name[IMAGE_SIZEOF_SHORT_NAME + 1] = { 0 };
    memset(Name, 0, IMAGE_SIZEOF_SHORT_NAME + 1);
    int sectionNum = pNTHeaders->FileHeader.NumberOfSections;
    for (int i = 0; i < sectionNum; i++)
    {
        memcpy_s(Name, IMAGE_SIZEOF_SHORT_NAME, pSectionHeader->Name, IMAGE_SIZEOF_SHORT_NAME);
        printf("%d %s\nVirtualAddress: %08X, VirtualSize: %08X ==> %08X\nPointerToRawData: %08X, SizeOfRawData: %08X ==> %08X\n",
            i, Name,
            pSectionHeader->VirtualAddress,
            pSectionHeader->Misc.VirtualSize,
            pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize,
            pSectionHeader->PointerToRawData,
            pSectionHeader->SizeOfRawData,
            pSectionHeader->PointerToRawData + pSectionHeader->SizeOfRawData
        );

        if (pSectionHeader->SizeOfRawData == 0)
        {
            // fill with zero
            pSectionHeader->VirtualAddress;
            pSectionHeader->Misc.VirtualSize;
        }
        else
        {
            // File -> SizeOfRawData
            int dataLen = pSectionHeader->SizeOfRawData > pSectionHeader->Misc.VirtualSize ? pSectionHeader->SizeOfRawData : pSectionHeader->Misc.VirtualSize;
            char* dest = (char*)(newFileBuffer + pSectionHeader->PointerToRawData);
            char* src = (char*)(memBuffer + pSectionHeader->VirtualAddress);
            memcpy_s(dest, dataLen, src, pSectionHeader->Misc.VirtualSize);
        }

        pSectionHeader++;
    }

    pSectionHeader--;
    sizeOfPERawData = pSectionHeader->PointerToRawData + pSectionHeader->SizeOfRawData;

    // release heap memory later
    return newFileBuffer;
}

int main(int argc, char** argv)
{
    TCHAR szPath[MAX_PATH];
    if (argc <= 1)
    {
        printf("Please use [ReadFile.exe] [file]\n");

        // use default test
        GetFile(szPath);
    }
    else
    {
        printf("%d %s\n", argc, argv[1]);
        strncpy_s(szPath, argv[1], strlen(argv[1]));
    }

    char* fileBuffer = NULL;
    bool bRet = ReadFile(szPath, &fileBuffer);
    if (bRet)
    {
        BYTE* memBuffer = FileToMemory((BYTE*)fileBuffer);

        DWORD sizeOfPERawData = 0;
        BYTE* newFileBuffer = MemoryToFile((BYTE*)memBuffer, sizeOfPERawData);

        FILE* fpNewFile = nullptr;
        errno_t error = fopen_s(&fpNewFile, "New.exe", "wb");
        if (error == 0)
        {
            fwrite(newFileBuffer, 1, sizeOfPERawData, fpNewFile);
            fclose(fpNewFile);
        }

        // release memory
        if (newFileBuffer)
        {
            delete newFileBuffer;
            newFileBuffer = nullptr;
        }

        // release memory
        if (memBuffer)
        {
            delete memBuffer;
            memBuffer = nullptr;
        }
    }
}


内容概要:本文介绍了一个基于冠豪猪优化算法(CPO)的无人机三维路径规划项目,利用Python实现了在复杂三维环境中为无人机规划安全、高效、低能耗飞行路径的完整解决方案。项目涵盖空间环境建模、无人机动力学约束、路径编码、多目标代价函数设计以及CPO算法的核心实现。通过体素网格建模、动态障碍物处理、路径平滑技术和多约束融合机制,系统能够在高维、密集障碍环境下快速搜索出满足飞行可行性、安全性与能效最优的路径,并支持在线重规划以适应动态环境变化。文中还提供了关键模块的代码示例,包括环境建模、路径评估和CPO优化流程。; 适合人群:具备一定Python编程基础和优化算法基础知识,从事无人机、智能机器人、路径规划或智能优化算法研究的相关科研人员与工程技术人员,尤其适合研究生及有一定工作经验的研发工程师。; 使用场景及目标:①应用于复杂三维环境下的无人机自主导航与避障;②研究智能优化算法(如CPO)在路径规划中的实际部署与性能优化;③实现多目标(路径最短、能耗最低、安全性最高)耦合条件下的工程化路径求解;④构建可扩展的智能无人系统决策框架。; 阅读建议:建议结合文中模型架构与代码示例进行实践运行,重点关注目标函数设计、CPO算法改进策略与约束处理机制,宜在仿真环境中测试不同场景以深入理解算法行为与系统鲁棒性。
<think>嗯,用户提交了一个关于"Out of fast frame buffer stack memory error"的技术问题,看起来是图形处理或嵌入式系统开发中遇到的底层内存错误。结合系统指令要求用中文回答、规范数学格式、生成相关问题等要求,我需要结构化处理这个专业问题。 用户可能正在开发图形应用程序或嵌入式系统,遇到了帧缓冲区内存耗尽的问题。这个错误通常发生在显存分配失败时,尤其是需要快速访问的专用内存区域。从用户简洁的提问方式看,ta应该是有相关开发经验的技术人员,需要直接的解决方案而非基础概念解释。 参考站内引用中提到的内存分配失败场景[^2],这和帧缓冲区内存错误有相似之处,都是资源耗尽的体现。不过帧缓冲区更特指图形处理单元(GPU)的专用内存,需要区别于普通内存管理。 关键技术点需要分三部分展开:首先是诊断内存分配模式,因为静态分配和动态分配的处理策略完全不同;其次是优化内存使用策略,这里会涉及缓存算法和纹理压缩等专业方案;最后是系统级调整,包括驱动参数和硬件配置。每个方案都要给出可操作的具体命令或代码示例,比如Linux下修改grub参数、OpenGL的纹理压缩标志等。 考虑到用户环境差异,需要覆盖多平台解决方案:Windows的注册表调整、Linux的内核参数、嵌入式系统的交叉编译选项等。对于开发者,提供glGetError()和Vulkan内存类型查询的调试代码片段会很有帮助。 生成的相关问题要引导用户深入排查:从性能分析工具到架构设计,再到替代渲染方案。这些问题能帮助用户系统性解决根本问题,而不仅是临时修复。 特别注意数学格式要求:所有行内公式如显存计算公式$W \times H \times C \times B$必须用$...$包裹,独立公式如内存带宽计算则用$$...$$单独呈现。虽然当前问题涉及数学内容不多,但在性能分析部分仍需要规范表达量化关系。</think>"Out of fast frame buffer stack memory"错误通常发生在图形应用程序(如游戏、CAD软件、嵌入式图形系统)尝试分配显存/帧缓冲内存失败时。以下是系统性的解决方案: --- ### **1. 诊断根本原因** * **检查显存需求**: $$ \text{显存需求} = \text{分辨率} \times \text{色深} \times \text{缓冲区数量} + \text{纹理/几何数据} $$ 计算当前应用所需显存是否超出硬件限制。 * **监控工具**: * Windows:GPU-Z、任务管理器性能标签 * Linux:`nvidia-smi` (NVIDIA)、`radeontop` (AMD)、`intel_gpu_top` (Intel) * 嵌入式系统:供应商提供的调试工具(如Qt for Embedded Linux的`eglinfo`) --- ### **2. 优化显存使用** * **降低分辨率/色深**: ```c // OpenGL示例:降低颜色缓冲区位深 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); // 改为16位色深(若支持) glutInitDisplayString("rgba depth double samples=4"); ``` * **减少缓冲区数量**: * 关闭不必要的`MSAA`(多重采样抗锯齿)或降低采样数 * 避免同时启用多个离屏渲染缓冲区(FBO) * **纹理压缩**: ```c // 使用压缩纹理格式(如ASTC、ETC2) glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_ASTC_4x4, width, height, 0, size, data); ``` * **动态资源管理**: * 及时释放未使用的纹理/缓冲区:`glDeleteTextures()`, `glDeleteFramebuffers()` * 使用`LRU缓存`策略管理资源 --- ### **3. 系统级调整** * **更新图形驱动**: * 确保使用最新稳定版驱动(修复可能的内存管理缺陷)[^1] * **调整显存分配参数**: * **Linux**:在`/etc/default/grub`中为内核添加参数: ```bash GRUB_CMDLINE_LINUX="... vga=791 vmalloc=256M" ``` * **嵌入式系统**:修改`bootloader`参数(如U-Boot的`video=`选项) * **增加交换空间**(临时缓解): ```bash sudo fallocate -l 2G /swapfile # 创建2GB交换文件 sudo mkswap /swapfile sudo swapon /swapfile ``` --- ### **4. 代码级调试** * **检查内存泄漏**: ```c // OpenGL调试扩展 glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(debugCallback, NULL); ``` * **验证显存分配**: ```c glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { // 处理分配失败 } ``` --- ### **5. 硬件与架构优化** * **升级硬件**:增加物理显存(如更换显卡) * **使用分块渲染**(Tiled Rendering): ```python # 伪代码:将场景分割为瓦片渲染 for tile in scene.tiles: render_tile(tile) flush_gpu_memory() ``` * **切换到轻量渲染器**:如从OpenGL ES迁移到`Vulkan`(更精细的内存控制)[^4] --- ### **典型应用场景示例** | **场景** | **优化策略** | |-------------------|--------------------------------| | 嵌入式GUI | 启用`Qt Quick 2D Renderer`替代OpenGL | | 高分辨率游戏 | 动态降低非焦点区域渲染精度 | | 科学可视化 | 使用GPU稀疏纹理(Sparse Texturing) | > **关键提示**:在嵌入式系统中,此错误常与`DirectFB`或`Wayland`合成器配置相关,需检查`/etc/xorg.conf`或合成器参数(如Weston的`--tile-size`)[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值