使用SDL2的c程序中的内存泄漏

问题描述 投票:0回答:1

我的程序在屏幕上绘制一个可以移动的 3D 立方体。当程序刚刚运行或尝试移动立方体时,随着时间的推移,会出现一些内存泄漏。另外,每当立方体靠近屏幕并“超过它”时,我都会遇到内存使用量的巨大峰值,有时它会达到疯狂的值,超过 GBS 的内存,甚至导致我的计算机死机。我见过有人说 sdl2 库本身存在一些小泄漏,应该忽略它们,但这有点太多了 :o.

代码如下:

#define SDL_MAIN_HANDLED
#include <stdio.h>
#include <stdbool.h>
#include <SDL2/SDL.h>

const int gWidth = 640;
const int gHeight = 480;

const float moveSpeed = 5.0f;
const int fl = 300;
const int centerX = gWidth / 2;
const int centerY = gHeight / 2;
const int centerZ = 1000;

SDL_Window* gWindow = NULL;
SDL_Renderer* gRenderer = NULL;

struct Vector3 {
      float x; float y; float z;
};

bool init() {
      if(SDL_Init(SDL_INIT_VIDEO) != 0) {
        printf("SDL Erorr: %s", SDL_GetError());
        return false;
    }
    gWindow = SDL_CreateWindow("hi", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, gWidth, gHeight, 0);
    if(gWindow == NULL) {
        printf("SDL Erorr: %s", SDL_GetError());
        return false;
    }
    gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_PRESENTVSYNC);
    if(gWindow == NULL) {
        printf("SDL Erorr: %s", SDL_GetError());
        return false;
    }
    return true;
}

void close() {
      SDL_DestroyRenderer(gRenderer);
      SDL_DestroyWindow(gWindow);
      SDL_Quit();
}

// moves 8 points
void translateModel(struct Vector3* input, float x, float y, float z) {
      for(int i = 0; i < 8; i++) {
            input[i].x += x;
            input[i].y += y;
            input[i].z += z;
      }
}

// project 3D point onto the 2D screen
SDL_Point projectPoint(struct Vector3 input) {
      float perspective = 1.0f;
      float distance = fl + input.z + centerZ;
      // comparing floating points
      if(distance > 1 || distance < -1) {
            perspective = fl / distance;
      }
      SDL_Point p;
      // + centerX makes origin sit in the middle of the screen
      p.x = input.x * perspective + centerX; 
      p.y = input.y * perspective + centerY; 
      return p;
}

// connects 8 points to form a cube
void drawCube(struct Vector3* input) {
      for(int i = 0; i < 4; i++) {
            SDL_Point p0 = projectPoint(input[i]); // 0 1   1 2   2 3   3 0
            SDL_Point p1 = projectPoint(input[(i + 1) % 4]);
            SDL_RenderDrawLine(gRenderer, p0.x, p0.y, p1.x, p1.y);
      }
      for(int i = 0; i < 4; i++) {
            SDL_Point p0 = projectPoint(input[i + 4]);
            SDL_Point p1 = projectPoint(input[(i + 1) % 4 + 4]);
            SDL_RenderDrawLine(gRenderer, p0.x, p0.y, p1.x, p1.y);
      }
      for(int i = 0; i < 4; i++) {
            SDL_Point p0 = projectPoint(input[i]);
            SDL_Point p1 = projectPoint(input[(i + 4)]);
            SDL_RenderDrawLine(gRenderer, p0.x, p0.y, p1.x, p1.y);
      }
}

void draw(struct Vector3* input) {
      SDL_SetRenderDrawColor(gRenderer, 0x00, 0x00, 0x00, 0xFF);
      SDL_RenderClear(gRenderer);
      SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
      
      drawCube(input);

      SDL_RenderPresent(gRenderer);
}

int main() {
      // initialize SDL stuff
      init();
      bool isRunning = true;
      SDL_Event e;
      const Uint8* gKeyStates = SDL_GetKeyboardState(NULL);

      struct Vector3 points[8] = {
            [0] = {-150, -150, 150},
            [1] = {150, -150, 150},
            [2] = {150, 150, 150},
            [3] = {-150, 150, 150},
            [4] = {-150, -150, -150},
            [5] = {150, -150, -150},
            [6] = {150, 150, -150},
            [7] = {-150, 150, -150},
      };

      while(isRunning) {
            SDL_PollEvent(&e);
            if(e.type == SDL_QUIT) {
                  return false;
            }
            if(gKeyStates[SDL_SCANCODE_LEFT]) { // add "tickrate" so that speed matches with diffrent frame rates
                  translateModel(points, -moveSpeed, 0, 0);
            }
            if(gKeyStates[SDL_SCANCODE_RIGHT]) {
                  translateModel(points, moveSpeed, 0, 0);
            }
            if(gKeyStates[SDL_SCANCODE_UP]) {
                  translateModel(points, 0, 0, -moveSpeed);
            }
            if(gKeyStates[SDL_SCANCODE_DOWN]) {
                  translateModel(points, 0, 0, moveSpeed);
            }
            draw(points);
      }
      close();

      return 0;
}

我尝试使用 porgram dr 内存,它产生了这个

Error #1: UNADDRESSABLE ACCESS beyond top of stack: reading 0x0000002b24fff860-0x0000002b24fff868 8 byte(s)
# 0 .text
# 1 _pei386_runtime_relocator
# 2 __tmainCRTStartup
# 3 .l_start
# 4 KERNEL32.dll!BaseThreadInitThunk
Note: @0:00:00.253 in thread 6472
Note: 0x0000002b24fff860 refers to 776 byte(s) beyond the top of the stack 0x0000002b24fffb68
Note: instruction: or     $0x0000000000000000 (%rcx) -> (%rcx)

Error #2: UNINITIALIZED READ: reading 0x0000002b24ffeb7c-0x0000002b24ffeb80 4 byte(s) within 0x0000002b24ffeb78-0x0000002b24ffeb80
# 0 system call NtGdiOpenDCW parameter value #5
# 1 gdi32full.dll!hdcCreateDCW                               +0xb1     (0x00007ff846b2f8e2 <gdi32full.dll+0x1f8e2>)
# 2 GDI32.dll!bCreateDCW
# 3 GDI32.dll!CreateDCW
# 4 SDL2.dll!?                                               +0x0      (0x00007ff8042e484e <SDL2.dll+0x12484e>)
# 5 SDL2.dll!?                                               +0x0      (0x00007ff8042e4bd3 <SDL2.dll+0x124bd3>)
# 6 USER32.dll!_ClientMonitorEnumProc
# 7 SDL2.dll!?                                               +0x0      (0x00007ff8042e4e57 <SDL2.dll+0x124e57>)
# 8 SDL2.dll!?                                               +0x0      (0x00007ff8042e8546 <SDL2.dll+0x128546>)
# 9 SDL2.dll!?                                               +0x0      (0x00007ff8042aeea0 <SDL2.dll+0xeeea0>)
#10 SDL2.dll!?                                               +0x0      (0x00007ff8041c16e7 <SDL2.dll+0x16e7>)
#11 init 
#12 main 
Note: @0:00:01.236 in thread 6472

整个日志文件很长,所以我只包含前两个错误

c memory sdl-2
1个回答
0
投票

在“糟糕”的相机位置期间,确保您传入的线条

SDL_RenderDrawLine()
不是超长(如数百万或数十亿像素)。

如果它们超长并且 SDL 处于

SDL_RENDERLINEMETHOD_POINTS
模式,它将达到
SDL_render.c:RenderDrawLineBresenham()
,其内部分配与线的长度(以像素为单位)成比例。

处理超长线路的一些选项:

  • 在调用之前将线条剪裁到渲染器范围
    SDL_RenderDrawLine()
  • 使用 SDL 提交错误以在内部进行剪辑
    SDL_RenderDrawLine()
  • SDL_RENDER_LINE_METHOD
    提示设置为
    2
    3
    ,以便渲染器代码避免
    RenderDrawLineBresenham()
© www.soinside.com 2019 - 2024. All rights reserved.