Никогда не видел эту ошибку компоновщика в моей жизни, пока я не начал программировать приложения 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 для динамического выделения всего, но класс векторного шаблона каким-то образом использует новый оператор.