首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SDL_LockTexture() / AddressSanitizer /双人免费

SDL_LockTexture() / AddressSanitizer /双人免费
EN

Stack Overflow用户
提问于 2018-08-19 14:30:58
回答 1查看 536关注 0票数 1

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

最近,我已经开始使用AddressSanitizer来帮助调试我的应用程序,并发现可能的内存泄漏(对于我的应用程序来说,瓦兰太慢了)。AddressSanitizer告诉我一个严重的内存泄漏,我正在努力解决这个问题。下面是一个独立的、完全可编译的示例,它说明了我的问题。

代码语言:javascript
复制
#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试图释放分配给我的像素缓冲区的内存,但是失败并导致内存泄漏。有趣的是,如果我用:

代码语言:javascript
复制
SDL_UpdateTexture(texture, NULL, pixels, m_Width * 3);

然后我可以自行释放像素,从而修复内存泄漏。有人知道这是怎么回事吗?这仅仅是来自AddressSanitizer的假阳性吗?

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

非常感谢您的阅读,我非常感谢您的帮助。

阿曼达

EN

回答 1

Stack Overflow用户

发布于 2018-09-12 16:15:09

注意,SDL_LockTexture()的签名使用指向指针的指针。这是一个提示,说明您不应该传递自己的缓冲区。您正在泄漏,因为SDL_LockTexture()正在更改指针的值,您要传递的指针地址指向它自己的内部缓冲区,现在您无法删除您(无用的)分配的缓冲区。显然,出现了双空闲,因为您正在删除一个不属于您的缓冲区,该缓冲区在您调用SDL_DestroyTexture()时已经释放了(可能,我不确定确切的实现)。

还要注意,数据可能实际上并不是您所期望的格式。SDL_CreateTexture()可以忽略您的建议,并为您提供后端支持的“最接近”的匹配格式。您需要查询纹理的实际格式,以了解如何处理像素。

正如注释中所指出的:如果希望以自己的格式提供自己的像素,则必须使用SDL_UpdateTexture(),但这当然要慢得多。

关于地址消毒剂的注意事项:它不会产生假阳性。如果它报告了一个问题,你确实有一个问题。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51918664

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档