取消引用指针时出现 SIGSEGV 分段错误

SIGSEGV Segmentation Fault when dereferencing a pointer

我知道已经有几个与此类似的问题,但我已经通读了它们,其中 none 似乎涵盖了我的具体问题...

我正在尝试从结构中取消引用 public 指针,但它抛出了 SIGSEV 分段错误,即使指针确实指向一个值

它打印了 1 和 2 但没有进一步打印。如果我将其更改为引用指针而不是值,错误将移动到我引用该值的任何地方,所以我知道问题出在取消引用上,而不是该行的其余部分。

如果您需要查看我的更多代码以查找问题,请直接询问。我只是不想让您不必要地浏览数百行...

#include <vector>
#include "Entities.cpp"

struct Chunk {
    public:
        std::vector<BaseEntity>* environment; // this is what I'm trying to access

        Chunk() {
            environment = new std::vector<BaseEntity>(1); // this is where init

            environment->push_back(Grass()); // adding something to it works fine
        }

        ~Chunk() {
            delete(environment);
        }
};

class World {
    public:
        Chunk* loaded[3][3];

        World() {
            for (int x = 0; x < 3; x++)
                for (int y = 0; y < 3; y++) {
                    loaded[x][y] = new Chunk();
                }
        }

        ~World() {
            for (int x = 0; x < 3; x++)
                for (int y = 0; y < 3; y++) {
                    delete(loaded[x][y]);
                }
        }
};

这是访问它的代码(在另一个 class 和文件中)

void render(SDL_Renderer* gRenderer, Atlas* atlas, World* world, int SCREEN_WIDTH, int SCREEN_HEIGHT) {
        printf("1");
        for (int x = 0; x < 3; x++)
            for (int y = 0; y < 3; y++) {
                printf("2");
                std::vector<BaseEntity> env =
                        *(world->loaded[x][y]->environment); // here is where the error occurs
                printf("3");

                printf('0' + env.size() + "");
                printf("a");

                for (const auto& a : env) {
                    printf("b");
                    drawTexture(gRenderer, atlas, a.atlasID,
                            SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
                }
                printf("4");
            }
        printf("5");

    }

这是调用它的代码:

int main(int argv, char** args) {
    SDL_Init( SDL_INIT_VIDEO );

    //The window we'll be rendering to
    SDL_Window* gWindow = SDL_CreateWindow(
         title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );

    if (gWindow == NULL) {
        printf("window error");
    }
    
    //Create renderer for window
    SDL_Renderer* gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED );
    if (gRenderer == NULL) {
        printf("renderer error");
    }

    bool quit = false; // quit flag

    //Event handler
    SDL_Event e;

    //nice little rendering class
    Renderer* renderer = new Renderer();

    //World
    World* world = new World();

    //Texture Atlas
    Atlas* atlas = new Atlas(SDL_GetWindowSurface( gWindow), gRenderer);


    //While application is running
        while( !quit )
        {
            //Handle events on queue
            while( SDL_PollEvent( &e ) != 0 )
            {

                switch(e.type) {
                    case SDL_QUIT: //User requests quit
                        quit = true;
                        break;
                }
                
            }

            //Clear screen
            //SDL_SetRenderDrawColor( gRenderer, 0, 0xFF, 0, 0xFF );
            SDL_RenderClear( gRenderer );

            renderer->render(gRenderer, atlas, world, SCREEN_WIDTH, SCREEN_HEIGHT);

            //Update the surface
            SDL_RenderPresent(gRenderer);
            //SDL_UpdateWindowSurface( gWindow );

        }

        delete (world, renderer, atlas);

        return 0;
}

我没有发现您的代码有直接问题(除了复制向量显然效率低下),但我 发现您的 printf 调试有问题.

  1. 您应该使用 fprintf(stderr, ...) 进行调试 printfs,以避免 stdio 缓冲,或调用 fflush(NULL).
    3 未打印的事实并不一定意味着 printf("3") 未达到。
  2. 您应该完全避免 printf 调试,并学会使用真正的调试器(GDB 或 LLDB)。
  3. 如果您 运行 您的程序带有 Address Sanitizer (-fsanitize=address);它可能会直接指出错误。

最后,在C++中书写时,避免使用C风格的数组,尤其是多级数组。请改用 vectors。

这分配了一个 std::vectorBaseEntity

的一个元素
environment = new std::vector<BaseEntity>(1); // this is where init

然后附加 Grass 的另一个元素

environment->push_back(Grass()); // adding something to it works fine

但也许这是第一个问题,因为向量只包含 BaseEntitys,参见 What is object slicing?


这会访问给定向量的第一个元素,这不是附加的 Grass 而是 new std::vector<BaseEntity>(1)

中默认构造的 BaseEntity 对象
std::vector<BaseEntity> env = *(world->loaded[x][y]->environment); // here is where the error occurs

访问指针应该没有问题,因为它似乎已正确初始化。 但也许复制 BaseEntity 才是真正的问题。我会查看 BaseEntity(可能还有 Grass)的(复制)构造函数,看看是否存在一些有问题的代码。