Undefined ссылка на нового оператора

Никогда не видел эту ошибку компоновщика в моей жизни, пока я не начал программировать приложения PSP homebrew. Во всяком случае, я делаю аллегро, и в этом случае мне нужно стрелять снарядами или ракетами, и мне нужно использовать динамический и общий массив. Но мой компоновщик жалуется, что есть ссылка undefined на новый оператор. Ниже будет весь исходный код, makefile и сведения об ошибке.

Сведения об ошибке:

1>------ Build started: Project: PSP Asteroids, Configuration: Debug Win32 ------
1>  psp-g++ -I. -IC:/pspsdk/psp/sdk/include -O2 -G0 -Wall -I. -IC:/pspsdk/psp/sdk/include -O2 -G0 -Wall -fno-exceptions -fno-rtti -D_PSP_FW_VERSION=150   -c -o main.o main.cpp
1>  psp-gcc -I. -IC:/pspsdk/psp/sdk/include -O2 -G0 -Wall -D_PSP_FW_VERSION=150  -L. -LC:/pspsdk/psp/sdk/lib   main.o -lalleg -lpspgu -lpspirkeyb -lm -lpsppower -lpspaudio -lpsprtc  -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk -lc -lpspnet -lpspnet_inet -lpspnet_apctl -lpspnet_resolver -lpsputility -lpspuser -lpspkernel -o main.elf
1>  main.o: In function `std::vector<Missile*, std::allocator<Missile*> >::_M_insert_aux(__gnu_cxx::__normal_iterator<Missile**, std::vector<Missile*, std::allocator<Missile*> > >, Missile* const&)':
1>  main.cpp:(.text._ZNSt6vectorIP7MissileSaIS1_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS1_S3_EERKS1_[_ZNSt6vectorIP7MissileSaIS1_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS1_S3_EERKS1_]+0xb8): undefined reference to `operator new(unsigned int)'
1>  main.cpp:(.text._ZNSt6vectorIP7MissileSaIS1_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS1_S3_EERKS1_[_ZNSt6vectorIP7MissileSaIS1_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS1_S3_EERKS1_]+0x124): undefined reference to `operator delete(void*)'
1>  C:\pspsdk\bin\make: *** [main.elf] Error 1
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Makefile

TARGET = main
OBJS = main.o

CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = PSP Asteroids
LIBS = -lalleg -lpspgu -lpspirkeyb -lm -lpsppower -lpspaudio -lpsprtc 
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak 

main.cpp

#define ALLEGRO_NO_MAGIC_MAIN
#define WIDTH 480
#define HEIGHT 272
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>
#include <allegro.h>
#include <math.h>
#include <vector>
PSP_MODULE_INFO("PSP Asteroids", 0, 1, 1);
int check_bb_collision ( BITMAP* spr1, BITMAP* spr2, int x1, int y1, int x2, int y2)
{
    int b1_x = x1;
    int b2_x = x2;
    int b1_y = y1;
    int b2_y = y2;
    int b1_w = spr1->w;
    int b2_w = spr2->w;
    int b1_h = spr1->h;
    int b2_h = spr2->h;
    if ( ( b1_x > b2_x + b2_w - 1 )  ||  // is b1 on the right side of b2?
                ( b1_y > b2_y + b2_h - 1 )       ||  // is b1 under b2?
                ( b2_x > b1_x + b1_w - 1 )       ||  // is b2 on the right side of b1?
                ( b2_y > b1_y + b1_h - 1 ) )         // is b2 under b1?
    {
        // no collision
        return 0;
    }

    // collision
    return 1;
}
//Pass 2 Allegro bitmaps and their respective positions and this function
//returns true if there is a collision and false if theres not.
//The 2 bitmaps must be memory bitmaps of the same color depth.
int check_pp_collision_normal(BITMAP *spr1, BITMAP *spr2, int x1, int y1, int x2, int y2)
{
 int dx1, dx2, dy1, dy2; //We will use this deltas...
 int fx,fy,sx1,sx2; //Also we will use this starting/final position variables...
 int maxw, maxh; //And also this variables saying what is the maximum width and height...
 int depth; //This will store the color depth value...
 char CHARVAR; //We will use these to store the transparent color for the sprites...
 short SHORTVAR;
 long LONGVAR;

 if( !check_bb_collision(spr1, spr2, x1,y1, x2,y2) ) return 0; //If theres not a bounding box collision, it is impossible to have a pixel perfect collision right? So, we return that theres not collision...

 //First we need to see how much we have to shift the coordinates of the sprites...
 if(x1>x2) {
   dx1=0;      //don't need to shift sprite 1.
   dx2=x1-x2;  //shift sprite 2 left. Why left? Because we have the sprite 1 being on the right of the sprite 2, so we have to move sprite 2 to the left to do the proper pixel perfect collision...
   } else {
   dx1=x2-x1;  //shift sprite 1 left.
   dx2=0;      //don't need to shift sprite 2.
   }
 if(y1>y2) {
   dy1=0;
   dy2=y1-y2;  //we need to move this many rows up sprite 2. Why up? Because we have sprite 1 being down of sprite 2, so we have to move sprite 2 up to do the proper pixel perfect collision detection...
   } else {
   dy1=y2-y1;  //we need to move this many rows up sprite 1.
   dy2=0;
   }

 //Then, we have to see how far we have to go, we do this seeing the minimum height and width between the 2 sprites depending in their positions:
 if(spr1->w-dx1 > spr2->w-dx2) {
   maxw=spr2->w-dx2;
   } else {
   maxw=spr1->w-dx1;
   }
 if(spr1->h-dy1 > spr2->h-dy2) {
   maxh=spr2->h-dy2;
   } else {
   maxh=spr1->h-dy1;
   }
 maxw--;
 maxh--;

 fy=dy1;
 fx=dx1;
 dy1+=maxh;
 dy2+=maxh;
 sx1=dx1+maxw;
 sx2=dx2+maxw;

 depth=bitmap_color_depth(spr1); //Get the bitmap depth...

 if(depth==8) {
   CHARVAR=bitmap_mask_color(spr1); //Get the transparent color of the sprites...
   for(; dy1>=fy; dy1--,dy2--) { //Go through lines...
      for(dx1=sx1,dx2=sx2; dx1>=fx; dx1--,dx2--) { //Go through the X axis...
         if((spr1->line[dy1][dx1]!=CHARVAR) && (spr2->line[dy2][dx2]!=CHARVAR)) return 1; //Both sprites don't have transparent color in that position, so, theres a collision and return collision detected!
         }
      }
   } else {
   if(depth==16 || depth==15) {
     SHORTVAR=bitmap_mask_color(spr1); //Get the transparent color of the sprites...
     for(; dy1>=fy; dy1--,dy2--) { //Go through lines...
        for(dx1=sx1,dx2=sx2; dx1>=fx; dx1--,dx2--) { //Go through the X axis...
           if(( ((short *)spr1->line[dy1])[dx1]!=SHORTVAR) && ( ((short *)spr2->line[dy2])[dx2]!=SHORTVAR)) return 1; //Both sprites don't have transparent color in that position, so, theres a collision and return collision detected!
           }
        }
     } else {
     if(depth==32) {
       LONGVAR=bitmap_mask_color(spr1); //Get the transparent color of the sprites...
       for(; dy1>=fy; dy1--,dy2--) { //Go through lines...
          for(dx1=sx1,dx2=sx2; dx1>=fx; dx1--,dx2--) { //Go through the X axis...
             if(( ((long *)spr1->line[dy1])[dx1]!=LONGVAR) && ( ((long *)spr2->line[dy2])[dx2]!=LONGVAR)) return 1; //Both sprites don't have transparent color in that position, so, theres a collision and return collision detected!
             }
          }
       } else {
       if(depth==24) {
         CHARVAR=bitmap_mask_color(spr1)>>16; //if the order is RGB, this will contain B...
         SHORTVAR=bitmap_mask_color(spr1)&0xffff; //if the order is RGB, this will contain GR...
         for(; dy1>=fy; dy1--,dy2--) { //Go through lines...
            for(dx1=sx1,dx2=sx2; dx1>=fx; dx1--,dx2--) { //Go through the X axis...
               if( (*((short *)(spr1->line[dy1]+(dx1)*3))!=SHORTVAR) && (spr1->line[dy1][(dx1)*3+2]!=CHARVAR)  &&  (*((short *)(spr2->line[dy2]+(dx2)*3))!=SHORTVAR) && (spr2->line[dy2][(dx2)*3+2]!=CHARVAR) ) return 1; //Both sprites don't have transparent color in that position, so, theres a collision and return collision detected!
               //I have tryed to avoid the above multiplications but it seems that GCC optimizes better than I :-))
               }
            }
         }
       }
     }
   }

 //If we have reached here it means that theres not a collision:
 return 0; //Return no collision.
 }
//Finds the magnitude from a point in 2d.
double magnitude(int x, int y)
{

    return sqrt((x * x) + (y* y));
}
char* itoa(int val, int base){

    static char buf[32] = {0};

    int i = 30;

    for(; val && i ; --i, val /= base)

        buf[i] = "0123456789abcdef"[val % base];

    return &buf[i+1];

}
// static class that contain special game constants
class Constants
{
    public:
        static const double PI = 3.14159265358979323846;
        static const double PIOVER4 = (3.14159265358979323846 / 4);
        static const double TWOPI = (2 * 3.14159265358979323846);
        static const double PIOVER2 = (3.14159265358979323846 / 2);
        static const unsigned int MAXBULLETS = 5;
};
// Clamp
inline float clamp(float x, float min, float max)
{
    return x < min ? min : (x > max ? max : x);
}
// The ship class
class Ship
{
    public:
        double X;
        static const double Y = (272 - 64);
        double angle;
        void Init(int x)
        {

            angle = 0;
            X = x;
        }
        void MoveLeft()
        {
            X -= 2;

        }
        void MoveRight()
        {
            X += 2;
        }

        void Draw(BITMAP* buffer, BITMAP* sprite, int frame)
        {
            X = clamp(X, 0, 480);
            draw_sprite(buffer, sprite, X, Y);
        }
};
class Missile
{
    private:
        static const double angle = (3.14159265358979323846 / 2);
    public:
        bool Alive;
        static const int V = 5;
        double X;
        double Y;
        void Init(bool alive, int x, int y)
        {
            Alive = alive;
            X = x;
            Y = y;
        }
        void Update()
        {
            X += V * cos(angle);
            Y += V * sin(angle);
        }
        void Kill()
        {
            Alive = false;
        }
        void Draw(BITMAP* buffer, BITMAP* sprite)
        {
            draw_sprite(buffer, sprite, X, Y);
        }
};
std::vector<Missile*>* bullets = (std::vector<Missile*>*)malloc(1);
void FireBullet(Ship* s)
{
    if (bullets->size() < Constants::MAXBULLETS)
    {
        Missile* missile = (Missile*)malloc(1);
        missile->Init(true, s->X, s->Y);
        bullets->push_back(missile);
    }
}

void CleanUp()
{
    for(unsigned int index = 0; index < bullets->size(); index++)
    {

        if (bullets->at(index)->Alive == false)
        {
            bullets->erase(bullets->begin() + index);
        }
    }
}
void UpdateBullets()
{
    for(unsigned int index = 0; index < bullets->size(); index++)
    {
        if (bullets->at(index)->Y < 0)
        {
            bullets->at(index)->Update();
        }
        else
        {
            bullets->at(index)->Kill();
        }
    }
}
void DrawBullets(BITMAP* buffer, BITMAP* sprite)
{
    for(unsigned int index = 0; index < bullets->size(); index++)
    {
        if (bullets->at(index)->Alive == true)
        {
            bullets->at(index)->Draw(buffer, sprite);
        }
    }
}
//Entry point of the application
int main(void)
{   

    Ship* s = (Ship*)malloc(1);
    int x = (WIDTH / 2) - 64;
    allegro_message("Initialzing ship class");
    s->Init(x);
    int frame = 0;
    BITMAP* buffer = NULL;
    BITMAP* background = NULL;
    BITMAP* ship = NULL;
    SceCtrlData pad;
    bool done = false;
    allegro_message("Initializing Game...");
    int rval = allegro_init();
    if (allegro_init() != 0)
    {
        allegro_message("Error initializing Game Because it returned: %i", rval);
        return 1;
    }
    allegro_message("Setting Graphics Mode...Press X To Begin Game");
    set_color_depth(32);
    int ret = set_gfx_mode(GFX_AUTODETECT,480,272,0,0);
    if (ret != 0)
    {
        allegro_message("Error setting grahpic mode! Because of it returned: %i", ret);
        return ret;
    }
    background = load_bmp("background.bmp", NULL);
    ship = load_bmp("ship.bmp", NULL);
    BITMAP* m = load_bmp("missile.bmp", NULL);
    if (background == NULL || ship == NULL || m != NULL){
        allegro_message("Couldn't load one or more sprites...");
        return 0;
    }
    buffer = create_bitmap(WIDTH, HEIGHT);
    if (buffer == NULL)
    {
        allegro_message("Couldn't create buffer!");
        return 0;
    }
    int previousx = 0;
    int previousy = 0;
    while(!done)
    {

        sceCtrlReadBufferPositive(&pad, 1); 
        if (pad.Buttons & PSP_CTRL_START)
        {
            done = true;
        }
        else if (pad.Buttons & PSP_CTRL_CROSS)
        {
            FireBullet(s);
        }
        else if (pad.Buttons & PSP_CTRL_LEFT)
        {
            s->MoveLeft();
        }
        else if (pad.Buttons & PSP_CTRL_RIGHT)
        {
            s->MoveRight();
        }
        UpdateBullets();
        CleanUp();
        clear(buffer);
        draw_sprite(buffer, background, 0, 0);
        s->Draw(buffer, ship, frame);
        DrawBullets(buffer, ship);
        masked_blit(buffer, screen, 0, 0, 0, 0, WIDTH, HEIGHT);
        if (frame == (60 * 10))
        {
            frame = 0;
        }
        frame++;
        vsync();
        previousx = pad.Lx;
        previousy = pad.Ly;

    }
    allegro_message("Clearing resources!");
    clear(buffer);  
    clear(ship);
    clear(background);
    clear(screen);
    allegro_message("Thank you for playing!");
    return 0;
}
END_OF_MAIN()

Если эта ошибка не может быть исправлена, есть работа. Как и то, что я могу использовать, не использует новый оператор. Я имею в виду, что я использую malloc для динамического выделения всего, но класс векторного шаблона каким-то образом использует новый оператор.

Ответ 1

Похоже, вы используете gcc как обертка компоновщика, а не g++. Таким образом, стандартная среда исполнения С++ не связана, и оператор new не может быть найден. Вы должны либо использовать g++ для связи, либо указать время выполнения С++ самостоятельно, обычно это -lstdc++.