gpt4 book ai didi

c++ - SDL_LockTexture()/AddressSanitizer/双免

转载 作者:行者123 更新时间:2023-11-30 03:21:42 27 4
gpt4 key购买 nike

我的项目广泛使用 SDL2-2.0.8 来显示来自各种科学成像相机的数据帧。我的实际项目使用的是 wxWidgets 3.1.1 和 SDL_CreateWindowFrom(xid),而不是 SDL_CreateWindow()。

我最近开始使用 AddressSanitizer 来帮助调试我的应用程序并查找可能的内存泄漏(Valgrind 对我的应用程序来说太慢了)。 AddressSanitizer 通知我存在严重的内存泄漏,我正在努力修复。下面是一个独立的完全可编译的例子,它说明了我的问题。

#include <iostream>
#include <unistd.h>
#include <random>

#include <SDL2/SDL.h>

int main()
{

SDL_Window *window = nullptr;
SDL_Renderer* renderer = nullptr;
SDL_Texture *texture = nullptr;

uint8_t *pixels = new uint8_t[640 * 480 * 3];

// Random Numbers
std::mt19937 rng;
rng.seed(std::random_device()());
std::uniform_int_distribution<std::mt19937::result_type> random(0, 255);

int pitch;

if ((window = SDL_CreateWindow("Test", 0, 0, 640, 480, 0)) == nullptr)
{
std::cerr << SDL_GetError() << "\n";
return -1;
}

if ((renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED)) == nullptr)
{
std::cerr << SDL_GetError() << "\n";
return -1;
}

// Create the SDL Texture
if ((texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, 640, 480)) == nullptr)
{
std::cerr << SDL_GetError() << "\n";
return -1;
}

int counter = 0;

while (counter < 500)
{
SDL_LockTexture(texture, nullptr, (void**) &pixels, &pitch);

// Create greyscale noise - a bit like old television sets without an antenna
for (int n = 0; n < 640 * 480 * 3; n += 3)
{
int random_pix = random(rng);
pixels[n] = random_pix;
pixels[n + 1] = random_pix;
pixels[n + 2] = random_pix;
}

SDL_UnlockTexture(texture);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);

counter++;
}

// If the following line is uncommented and delete [] pixels commented, then I get a double-free in SDL
//free(pixels);

SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);

// This line causes a double-free error, if it's commented out then I get a memory leak of 921600 bytes
delete[] pixels;

atexit(SDL_Quit);

return 0;
}

似乎 SDL 正在尝试取消分配分配给我的像素缓冲区的内存,但失败并导致内存泄漏。有趣的是,如果我使用:

SDL_UpdateTexture(texture, NULL, pixels, m_Width * 3);

然后我可以自己释放像素,从而修复内存泄漏。有人知道发生了什么事吗?这仅仅是 AddressSanitizer 的误报吗?

更多信息:我的项目是用 C++ 编写的,并在 Fedora 28 上使用 GCC-8 编译。AddressSanitizer 来自标准 Fedora 存储库。我知道你们中的许多人会认为我应该使用智能指针,但这样做需要对我的项目进行重大重构,而我根本没有时间。

非常感谢阅读,我感谢提供的任何帮助。

阿曼达

最佳答案

请注意 SDL_LockTexture() 的签名采用指向指针的指针。这暗示您不应该传递自己的缓冲区。您正在泄漏,因为 SDL_LockTexture() 正在更改您正在传递的 address 指针的值以指向它自己的内部缓冲区,现在您无法删除您的(无用的)分配缓冲。显然,双重释放正在发生,因为您正在删除一个不属于您的缓冲区,该缓冲区在您调用 SDL_DestroyTexture() 时已经被释放(可能,我不确定确切的实现)。

另请注意,数据实际上可能不是您期望的格式。 SDL_CreateTexture()随意忽略你的建议,给你后端支持的“最接近”的匹配格式。您需要查询纹理的实际格式才能知道如何处理像素。

如评论中所述:如果您想以自己的格式提供自己的像素,则必须使用 SDL_UpdateTexture(),但这当然会慢得多。

关于地址清理器的注释:它不会产生误报。如果它报告了一个问题,那么您确实遇到了问题。

关于c++ - SDL_LockTexture()/AddressSanitizer/双免,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51918664/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com