如何确定这段记忆的来源change/corruption?

How do I determine the source of this memory change/corruption?

我目前正在开发一个 Vulkan 程序,我希望将其用作游戏引擎,但距离我的目标还很远。作为第一步,我只是尝试使用动态结构列表来渲染三角形以获取顶点和着色器等数据。为了解决平台特定的障碍,我使用 GLFW 创建 windows 和 Vulkan 表面。

现在我正在尝试从文件加载 SPIR-V 着色器并使用它们创建 VkShaderModules,我将在我的渲染管道中使用它。目前,我的代码的抽象部分是这样开始的:

main.c

#include "application.h"
#include "config.h"
#include "engine_vulkan.h"
#include "glfw/glfw3.h"

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
    printf("VLK Engine - Version %s\n", VERSION_NUMBER);
    if (enable_validation_layers) {
        printf("Validation layers enabled.\n");
    }
    printf("\n");

    struct VulkanData vulkan_data = {0};
    struct Application app = {.window = NULL, .vulkan_data = &vulkan_data, .objects = NULL};

    bool ret = application_init(&app);
    if (ret == false) {
        fprintf(stderr, "Cannot initialize applcation.\n");
        return EXIT_FAILURE;
    }

    while (application_loopcondition(&app)) {
        application_loopevent(&app);
    }

    application_close(&app);

    return EXIT_SUCCESS;
}

application.c

#include "application.h"

#include "engine_object.h"
#include "engine_vulkan.h"

bool application_init(struct Application *app) {
    bool ret;

    // Initialize GLFW
    glfwInit();

    // Create window
    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
    app->window = glfwCreateWindow(800, 600, "Vulkan window", NULL, NULL);
    if (app->window == NULL) {
        fprintf(stderr, "Failed to create window.\n");
        return false;
    }

    printf("Created window @ 0x%p\n", app->window);

    // Initialize game object list
    objectlink_init(app);

    // Create game objects
    struct RenderObjectCreateInfo ro_create_info = {.vertex_shader_path = "shaders/shader.vert.spv",
                                                    .fragment_shader_path =
                                                        "shaders/shader.frag.spv",
                                                    .is_static = true};
    struct RenderObject triangle = {0};
    object_init(app, &ro_create_info, &triangle);

    objectlink_add(app, &triangle);

    // Init Vulkan
    ret = vulkan_init(app);
    if (!ret) {
        fprintf(stderr, "Failed to initialize Vulkan.\n");
        return false;
    }

    return true;
}

bool application_loopcondition(struct Application *app) {
    // Close only if GLFW says so
    return !glfwWindowShouldClose(app->window);
}

void application_loopevent(struct Application *app) {
    // Poll for events like keyboard & mouse
    glfwPollEvents();
}

void application_close(struct Application *app) {
    // Destroy objects
    objectlink_destroy(app);
    // Close Vulkan instance
    vulkan_close(app);
    // End window & GLFW
    glfwDestroyWindow(app->window);
    glfwTerminate();
}

重要结构

struct Application {
    GLFWwindow *window;
    struct VulkanData *vulkan_data;
    struct RenderObjectLink *objects;
};

struct RenderObject {
    char *vertex_shader_path;
    struct ShaderFile vertex_shader_data;
    VkShaderModule vertex_shader;
    char *fragment_shader_path;
    struct ShaderFile fragment_shader_data;
    VkShaderModule fragment_shader;
    bool is_static;
};

struct RenderObjectCreateInfo {
    char *vertex_shader_path;
    char *fragment_shader_path;
    bool is_static;
};

struct RenderObjectLink {
    struct RenderObject *render_object;
    struct RenderObjectLink *next;
};

在我的应用程序结构中存储 VkShaderModule 时,我的应用程序出现问题。我的程序应该存储有关对象的信息的方式是在名为 appApplication 结构中,它指向 objects 字段中的 RenderObjectLink 的链表.我的函数 objectlink_initobjectlink_add 工作正常,但是当输入 GLFW 函数 glfwWindowShouldCloseglfwPollEvents

因为这两个函数在初始化 Vulkan 和创建着色器模块后是 运行,我发现 GDB 的 Vulkan 函数工作正常,我的数据结构只有在 运行宁宁 GLFW 循环功能。我已经使用硬件观察点对 GDB 进行了调试,以确定对这些着色器的引用(以及整个程序中的其他变量)在 进入 这些函数时发生变化。

Thread 1 hit Hardware watchpoint 4: app->objects->render_object->vertex_shader

Old value = (VkShaderModule) 0x731f0f000000000a
New value = (VkShaderModule) 0x40d625 <glfwPollEvents+43>
_glfwPlatformPollEvents () at C:/Users/dylanweber/Documents/C-Projects/vlkengine/main/glfw/src/win32_window.c:1878
1878    {

这种情况一直发生,但当我 运行 它时,变量会更改为不同的值。像 Dr. Memory 这样的内存分析工具(因为我正在使用 Windows 我不能使用 Valgrind)只显示系统 DLL 中的内存问题(比如通过 GLFW 读取控制器输入的 xinput)并且与我的程序无关。这种腐败的原因可能是什么?我可以使用什么 tools/resources 来查找这些问题?

根据代码,objectlink_add 函数接受第二个参数作为指针。最可能的用途是将指针添加到底层数据结构并保留它以供进一步引用。 post 中提到了渲染管道,这将是一种 link。

但是,该函数是从 application_init 过程调用的,该过程在其堆栈上分配了对象 triangle。当函数被 returned 时,它的堆栈已经消失,指针处的值变得无效。

有几种修复方法:

  1. 使用 malloc(或类似的)动态分配三角形结构。因此它不会在函数的 return 之后消失。这是最通用的方法,但它会在某个时间调用 free() 函数。

  2. triangle 对象可以是 static

  3. objectlink_add 可以复制某些内部结构中的 triangle 字段,但是,如果有多种类型的对象,它就会有问题。