Pb 与 C 程序:双重释放或损坏 (!prev)
Pb with a C programm : double free or corruption (!prev)
几年前,Benoit Mandelbrot 去世后,我决定做一个小程序来计算并看看他著名的分形集。很多年前我就做过(用turbo pascal语言)——这段时间,微积分花了一个晚上。所以我决定学一点C语言。有了 code::blocks 和 SDL 库(以及许多帮助),我终于编写了一个程序,我可以看到集合,并用鼠标放大内部。
效果很好,我还不到 windows。做同样的工作只需要 5 秒钟,而不是一晚上的微积分。
最近我决定发现linux,安装了与SDL相同的IDE。程序编译正常。它开始 运行,然后突然,当我使用鼠标时(左键上下单击 select 要放大的新方形区域),程序停止。
消息是:
double free or corruption (!prev)
st运行ge 的事情是,当我 运行 windows 下的代码时,它从未发生过。所以这对我来说是一件神秘的事情。我不知道这里的双重 免费 或 腐败 是什么意思。
为了更好的帮助你最终可以发给我,我加入了程序的代码(不完美)。也许有人可以找到问题所在...
该程序是为在 1680x1050 像素的屏幕上显示而编写的。
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <SDL/SDL.h>
//#include <SDL/SDL_ttf.h>
#define MAXITERATIONS 2000
#define CONST_DIVERGENCE 4
#define LONGUEUR_ECRAN 1680 //ajout d'une zone d'information et d'interaction de 630 pixels de large à droite de l'image.
#define LARGEUR_ECRAN 1050 // côté du carré où l'image est calculée.
int i , j ; /* i variable écran qui parcourt les abscisses entre 0 et LARGEUR_ECRAN
j les ordonnées entre 0 et LARGEUR_ECRAN */
int n ,t ; // itérations pour le calcul de convergence
int color,color1,color2,color3 ; //variable pour la couleur
int continuer = 1;
int recalculer = 1;
int recommencer = 1;
double XDEBUT = -2.05; // coordonnées du point de départ en haut à gauche du carré du plan complexe
double YDEBUT = -1.35;
double DELTA = 2.7 ; // longueur du côté du carré du plan complexe au départ
double xC =0 , yC = 0 ; // coordonnées du point du plan où on effectue les calculs
double xZ , yZ ; // coordonnées pour le calcul de la convergence
double xT = 0 ; // valeur temporaire d'allocation
double xTemp1 =0, yTemp1 = 0 ;
double xTemp2 =0, yTemp2 = 0 ;
int xTemoinDebut =1065; //variables pour positionner les cadres dans le Mandel témoin
int yTemoinDebut =15; //
int deltaTemoin =600; //
int x_1 , y_1; //variables pour positionner le cadre de zoom dans le grand Mandel
int x_2 , y_2; //
int xdebut , ydebut ; //
int delta; //
void placerPoint(SDL_Surface *surface, int x, int y, Uint32 pixel);
void petitMandel ();
int main(int argc, char *argv[])
{
while (recommencer == 1)
{
recommencer = 0;
recalculer =1;
continuer =1;
double XDEBUT = -2.05; // coordonnées du point de départ en haut à gauche du carré du plan complexe
double YDEBUT = -1.35;
double DELTA = 2.7 ; // longueur du côté du carré du plan complexe au départ
int xTemoinDebut =1065; //variables pour positionner les cadres dans le Mandel témoin
int yTemoinDebut =15; //
int deltaTemoin =600; //
double xC =0 , yC = 0 ; // coordonnées du point du plan où on effectue les calculs
double xZ , yZ ; // coordonnées pour le calcul de la convergence
double xT = 0 ; // valeur temporaire d'allocation
double xTemp1 =0, yTemp1 = 0 ;
double xTemp2 =0, yTemp2 = 0 ;
double tableauX [LARGEUR_ECRAN]= {0}; //tableau pour enregistrer les coordonnées réelles où on calcule
double tableauY [LARGEUR_ECRAN] = {0}; //
SDL_Init(SDL_INIT_VIDEO);
SDL_Surface *ecran = NULL,*rectangle=NULL/*,*texte = NULL*/;
// SDL_Event event;
SDL_Rect position;
ecran = SDL_SetVideoMode(LONGUEUR_ECRAN,LARGEUR_ECRAN, 32, SDL_HWSURFACE | SDL_FULLSCREEN); // mode vidéo : écran complet
SDL_LockSurface(ecran);
// SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 0)); // remplissage de l'écran en noir
// TTF_Font *police = NULL;
// SDL_Color couleurBleue = {0,0,255};
// TTF_Init();
// test d'erreur d'initialisation
/* if (TTF_Init () == -1)
{
fprintf(stderr, "Erreur d'initialisation de TTF_Init : %s \n",TTF_GetError ());
exit (EXIT_FAILURE);
}*/
/* TTF_Font *police = NULL;
SDL_Color couleurBleue = {0,0,255};
police = TTF_OpenFont("ankecall.ttf",20); police = TTF_OpenFont ("angelina.ttf",65);
texte = TTF_RenderText_Blended (police, "Voyage chez Mandelbrot ", couleurBleue);
while (continuer)
{
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
break;
}
position.x = 1060;
position.y = 630;
SDL_BlitSurface (texte, NULL, ecran, &position);
SDL_Flip(ecran);
}
SDL_FreeSurface(texte);
TTF_CloseFont(police);
TTF_Quit ();
*/
petitMandel(); //commande pour calculer un petit mandel témoin et un trait rouge
while (recalculer == 1)
{
for ( j = 0 ; j < LARGEUR_ECRAN ; j ++) // balayage vertical
{
yC = YDEBUT + (DELTA * j)/LARGEUR_ECRAN;
tableauY[j] = yC;
}
for ( i = 0 ; i < LARGEUR_ECRAN ; i ++) // balayage horizontal
{
xC = XDEBUT + (DELTA * i)/LARGEUR_ECRAN;
tableauX [i] = xC;
}
for ( j = 0 ; j < LARGEUR_ECRAN ; j ++) // balayage vertical
{
yC = YDEBUT + (DELTA * j)/LARGEUR_ECRAN;
for ( i = 0 ; i < LARGEUR_ECRAN ; i ++) // balayage horizontal
{
xC = XDEBUT + (DELTA * i)/LARGEUR_ECRAN;
n = 0 ; // initialisation du compteur de calcul
xZ = 0 ;
yZ = 0 ;
xT = 0 ;
while ( xZ*xZ + yZ*yZ < CONST_DIVERGENCE && n < MAXITERATIONS) /* boucle de calcul
elle s'arretera si xZ²+yZ² >= 4 ou si on a atteint le maximum d'itérations*/
{
xT = xZ ;// variable temporaire pour le calcul de yZ
xZ = xZ*xZ - yZ*yZ + xC ;
yZ = 2*yZ*xT + yC ;
n ++;
}
if (n< MAXITERATIONS) // On est en dehors de l'ensemble : mettre en gris
placerPoint(ecran,i,j,SDL_MapRGB(ecran->format,n,n,n));
else // On est dans l'ensemble : mettre en noir.
placerPoint(ecran,i,j,SDL_MapRGB(ecran->format,0,0,0));
}
}
SDL_UnlockSurface(ecran);
SDL_Flip(ecran);
recalculer = 0;
//Gestion des choix:
SDL_Event event;
while (continuer & (recalculer == 0))
{
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
break;
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT) //si clic gauche enfoncé
{
position.x = event.button.x;
position.y = event.button.y;
xTemp1 = tableauX [position.x];
yTemp1 = tableauY [position.y];
x_1 = position.x;
y_1 = position.y;
}
break;
case SDL_MOUSEBUTTONUP:
if (event.button.button == SDL_BUTTON_LEFT) //si clic gauche relaché
{
position.x = event.button.x;
position.y = event.button.y;
xTemp2 = tableauX [position.x];
yTemp2 = tableauY [position.y];
x_2 = position.x;
y_2 = position.y;
if (xTemp1 <xTemp2)
{
XDEBUT = xTemp1;
xdebut = x_1;
}
else
{
XDEBUT = xTemp2;
xdebut = x_2;
}
if (yTemp1<yTemp2)
{
YDEBUT = yTemp1;
ydebut = y_1;
}
else
{
YDEBUT = yTemp2;
ydebut = y_2;
}
if (fabs(xTemp1-xTemp2)<fabs(yTemp1-yTemp2))
{
DELTA = fabs(yTemp1-yTemp2);
delta = fabs(y_1-y_2);
}
else
{
DELTA = fabs(xTemp1-xTemp2);
delta = fabs(x_1-x_2);
}
// dessin du cadre blanc pour zoomer dans l'image principale
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE, 1, delta, 32, 0, 0, 0, 0); // Allocation du point
position.x = xdebut ; // Coordonnées du point à placer
position.y = ydebut ;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE,delta, 1, 32, 0, 0, 0, 0); // Allocation du point
position.x = xdebut ; // Coordonnées du point à placer
position.y = ydebut ;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE, 1, delta, 32, 0, 0, 0, 0); // Allocation du point
position.x = xdebut + delta; // Coordonnées du point à placer
position.y = ydebut ;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE, delta, 1, 32, 0, 0, 0, 0); // Allocation du point
position.x = xdebut ; // Coordonnées du point à placer
position.y = ydebut + delta;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
//dessin du cadre dans le mandelbrot témoin
xTemoinDebut = floor(xdebut*deltaTemoin/1050) + xTemoinDebut;
yTemoinDebut = floor(ydebut*deltaTemoin/1050) + yTemoinDebut;
deltaTemoin = floor(delta*deltaTemoin/1050);
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE, 1, deltaTemoin, 32, 0, 0, 0, 0); // Allocation du point
position.x = xTemoinDebut ; // Coordonnées du point à placer
position.y = yTemoinDebut ;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE, deltaTemoin, 1, 32, 0, 0, 0, 0); // Allocation du point
position.x = xTemoinDebut ; // Coordonnées du point à placer
position.y = yTemoinDebut ;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE, 1, deltaTemoin, 32, 0, 0, 0, 0); // Allocation du point
position.x = xTemoinDebut + deltaTemoin; // Coordonnées du point à placer
position.y = yTemoinDebut ;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE, deltaTemoin, 1, 32, 0, 0, 0, 0); // Allocation du point
position.x = xTemoinDebut ; // Coordonnées du point à placer
position.y = yTemoinDebut + deltaTemoin;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
recalculer = 1;
}
break;
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE)
continuer = 0 ;
if (event.key.keysym.sym == SDLK_r)
{
recommencer = 1 ;
recalculer = 0;
continuer =0;
}
if (event.key.keysym.sym == SDLK_s)
SDL_SaveBMP(ecran , "Mandel_50.bmp" ); // Enregistrement de l'image dans un fichier .bmp
break;
}
}
SDL_FreeSurface(rectangle); // Libération de la surface
}
}
SDL_Quit();
return EXIT_SUCCESS;
}
void petitMandel ()
{
int x=0,y=0;
SDL_Surface *ecran ;
ecran = SDL_GetVideoSurface();
SDL_LockSurface(ecran);
// trait rouge à droite de l'image
for (j=5; j<=1044; j++)
{
x = LARGEUR_ECRAN +5 ;
y = j ;
placerPoint(ecran,x,y,SDL_MapRGB(ecran->format,200,0,0));
}
SDL_Flip(ecran);
// instructions pour placer un petit Mandelbrot témoin dans la fenêtre "interactive"
for ( j = 0 ; j < 600 ; j ++) // balayage vertical
{
yC = YDEBUT + (DELTA * j)/600;
for ( i = 0 ; i < 600 ; i ++) // balayage horizontal
{
xC = XDEBUT + (DELTA * i)/600;
n = 0 ; // initialisation du compteur de calcul
xZ = 0 ;
yZ = 0 ;
xT = 0 ;
while ( xZ*xZ + yZ*yZ < CONST_DIVERGENCE && n < 500) /* boucle de calcul
elle s'arretera si xZ²+yZ² >= 4 ou si on a atteint le maximum d'itérations*/
{
xT = xZ ;// variable temporaire pour le calcul de yZ
xZ = xZ*xZ - yZ*yZ + xC ;
yZ = 2*yZ*xT + yC ;
n ++;
}
if (n< 500)
{
x = i + 1065 ; // Coordonnées du point à placer
y = j + 15;
color = floor (255-255*log(1+n*255/500)/log(256)); // calcul pour un dégradé plus progressif*/
placerPoint(ecran,x,y,SDL_MapRGB(ecran->format,color,color,color));
}
}
}
SDL_UnlockSurface(ecran);
SDL_Flip(ecran);
}
void placerPoint(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
int bpp = surface->format->BytesPerPixel;
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp)
{
case 1:
*p = pixel;
break;
case 2:
*(Uint16 *)p = pixel;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
{
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
}
else
{
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = pixel;
break;
}
}
看起来你在第 309 行额外释放了你的 SDL_Surface 指针 "rectangle" 一次。如果你评论那条线它运行正常。
当代码进入 switch 语句的 "SDL_MOUSEBUTTONUP" 情况时,它释放矩形,然后在第 309 行再次释放它。
你已经完成了运行 tableauX(如果有机会,可能还有 tableauY)。在它们之前放置断言:
assert(j < LARGEUR_ECRAN);
tableauY[j] = yC;
在所有访问前放一个断言(你的程序中有6个)。
我这样做了,但以下断言失败了
assert(position.x < LARGEUR_ECRAN)
xTemp1 = tableauX [position.x];
断言失败意味着 position.x >= LARGEUR_ECRAN。实际上它是1243,而LARGEUR_ECRAN是1050。注意,第一次越界访问不一定会失败,这就是为什么它不会在position.x到达时立即发生1050.
另请注意,在一个系统上 运行 "successfully"(即使存在错误)可能会在另一个系统上崩溃。
编辑:实际上,user5071535 似乎为您的错误消息找到了更有可能的来源,但我可能在这里发现了一个不同的错误。
未分配指针或非 NULL 指针上的每个 free() 都会 return 此错误。在尝试任何 free() 之前,请确认指针是否已分配或等于 NULL。无论如何,任何在未分配的指针或 improperly/insufficient 分配的指针上工作的尝试都会 return 这个错误。在 Windows 下,事情发生的情况有所不同,这只是 "lucky" 的问题:错误的代码将不可避免地在 "random" 时间在任何平台上失败。抱歉英语不好。
几年前,Benoit Mandelbrot 去世后,我决定做一个小程序来计算并看看他著名的分形集。很多年前我就做过(用turbo pascal语言)——这段时间,微积分花了一个晚上。所以我决定学一点C语言。有了 code::blocks 和 SDL 库(以及许多帮助),我终于编写了一个程序,我可以看到集合,并用鼠标放大内部。 效果很好,我还不到 windows。做同样的工作只需要 5 秒钟,而不是一晚上的微积分。
最近我决定发现linux,安装了与SDL相同的IDE。程序编译正常。它开始 运行,然后突然,当我使用鼠标时(左键上下单击 select 要放大的新方形区域),程序停止。
消息是:
double free or corruption (!prev)
st运行ge 的事情是,当我 运行 windows 下的代码时,它从未发生过。所以这对我来说是一件神秘的事情。我不知道这里的双重 免费 或 腐败 是什么意思。
为了更好的帮助你最终可以发给我,我加入了程序的代码(不完美)。也许有人可以找到问题所在... 该程序是为在 1680x1050 像素的屏幕上显示而编写的。
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <SDL/SDL.h>
//#include <SDL/SDL_ttf.h>
#define MAXITERATIONS 2000
#define CONST_DIVERGENCE 4
#define LONGUEUR_ECRAN 1680 //ajout d'une zone d'information et d'interaction de 630 pixels de large à droite de l'image.
#define LARGEUR_ECRAN 1050 // côté du carré où l'image est calculée.
int i , j ; /* i variable écran qui parcourt les abscisses entre 0 et LARGEUR_ECRAN
j les ordonnées entre 0 et LARGEUR_ECRAN */
int n ,t ; // itérations pour le calcul de convergence
int color,color1,color2,color3 ; //variable pour la couleur
int continuer = 1;
int recalculer = 1;
int recommencer = 1;
double XDEBUT = -2.05; // coordonnées du point de départ en haut à gauche du carré du plan complexe
double YDEBUT = -1.35;
double DELTA = 2.7 ; // longueur du côté du carré du plan complexe au départ
double xC =0 , yC = 0 ; // coordonnées du point du plan où on effectue les calculs
double xZ , yZ ; // coordonnées pour le calcul de la convergence
double xT = 0 ; // valeur temporaire d'allocation
double xTemp1 =0, yTemp1 = 0 ;
double xTemp2 =0, yTemp2 = 0 ;
int xTemoinDebut =1065; //variables pour positionner les cadres dans le Mandel témoin
int yTemoinDebut =15; //
int deltaTemoin =600; //
int x_1 , y_1; //variables pour positionner le cadre de zoom dans le grand Mandel
int x_2 , y_2; //
int xdebut , ydebut ; //
int delta; //
void placerPoint(SDL_Surface *surface, int x, int y, Uint32 pixel);
void petitMandel ();
int main(int argc, char *argv[])
{
while (recommencer == 1)
{
recommencer = 0;
recalculer =1;
continuer =1;
double XDEBUT = -2.05; // coordonnées du point de départ en haut à gauche du carré du plan complexe
double YDEBUT = -1.35;
double DELTA = 2.7 ; // longueur du côté du carré du plan complexe au départ
int xTemoinDebut =1065; //variables pour positionner les cadres dans le Mandel témoin
int yTemoinDebut =15; //
int deltaTemoin =600; //
double xC =0 , yC = 0 ; // coordonnées du point du plan où on effectue les calculs
double xZ , yZ ; // coordonnées pour le calcul de la convergence
double xT = 0 ; // valeur temporaire d'allocation
double xTemp1 =0, yTemp1 = 0 ;
double xTemp2 =0, yTemp2 = 0 ;
double tableauX [LARGEUR_ECRAN]= {0}; //tableau pour enregistrer les coordonnées réelles où on calcule
double tableauY [LARGEUR_ECRAN] = {0}; //
SDL_Init(SDL_INIT_VIDEO);
SDL_Surface *ecran = NULL,*rectangle=NULL/*,*texte = NULL*/;
// SDL_Event event;
SDL_Rect position;
ecran = SDL_SetVideoMode(LONGUEUR_ECRAN,LARGEUR_ECRAN, 32, SDL_HWSURFACE | SDL_FULLSCREEN); // mode vidéo : écran complet
SDL_LockSurface(ecran);
// SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 0)); // remplissage de l'écran en noir
// TTF_Font *police = NULL;
// SDL_Color couleurBleue = {0,0,255};
// TTF_Init();
// test d'erreur d'initialisation
/* if (TTF_Init () == -1)
{
fprintf(stderr, "Erreur d'initialisation de TTF_Init : %s \n",TTF_GetError ());
exit (EXIT_FAILURE);
}*/
/* TTF_Font *police = NULL;
SDL_Color couleurBleue = {0,0,255};
police = TTF_OpenFont("ankecall.ttf",20); police = TTF_OpenFont ("angelina.ttf",65);
texte = TTF_RenderText_Blended (police, "Voyage chez Mandelbrot ", couleurBleue);
while (continuer)
{
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
break;
}
position.x = 1060;
position.y = 630;
SDL_BlitSurface (texte, NULL, ecran, &position);
SDL_Flip(ecran);
}
SDL_FreeSurface(texte);
TTF_CloseFont(police);
TTF_Quit ();
*/
petitMandel(); //commande pour calculer un petit mandel témoin et un trait rouge
while (recalculer == 1)
{
for ( j = 0 ; j < LARGEUR_ECRAN ; j ++) // balayage vertical
{
yC = YDEBUT + (DELTA * j)/LARGEUR_ECRAN;
tableauY[j] = yC;
}
for ( i = 0 ; i < LARGEUR_ECRAN ; i ++) // balayage horizontal
{
xC = XDEBUT + (DELTA * i)/LARGEUR_ECRAN;
tableauX [i] = xC;
}
for ( j = 0 ; j < LARGEUR_ECRAN ; j ++) // balayage vertical
{
yC = YDEBUT + (DELTA * j)/LARGEUR_ECRAN;
for ( i = 0 ; i < LARGEUR_ECRAN ; i ++) // balayage horizontal
{
xC = XDEBUT + (DELTA * i)/LARGEUR_ECRAN;
n = 0 ; // initialisation du compteur de calcul
xZ = 0 ;
yZ = 0 ;
xT = 0 ;
while ( xZ*xZ + yZ*yZ < CONST_DIVERGENCE && n < MAXITERATIONS) /* boucle de calcul
elle s'arretera si xZ²+yZ² >= 4 ou si on a atteint le maximum d'itérations*/
{
xT = xZ ;// variable temporaire pour le calcul de yZ
xZ = xZ*xZ - yZ*yZ + xC ;
yZ = 2*yZ*xT + yC ;
n ++;
}
if (n< MAXITERATIONS) // On est en dehors de l'ensemble : mettre en gris
placerPoint(ecran,i,j,SDL_MapRGB(ecran->format,n,n,n));
else // On est dans l'ensemble : mettre en noir.
placerPoint(ecran,i,j,SDL_MapRGB(ecran->format,0,0,0));
}
}
SDL_UnlockSurface(ecran);
SDL_Flip(ecran);
recalculer = 0;
//Gestion des choix:
SDL_Event event;
while (continuer & (recalculer == 0))
{
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
break;
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT) //si clic gauche enfoncé
{
position.x = event.button.x;
position.y = event.button.y;
xTemp1 = tableauX [position.x];
yTemp1 = tableauY [position.y];
x_1 = position.x;
y_1 = position.y;
}
break;
case SDL_MOUSEBUTTONUP:
if (event.button.button == SDL_BUTTON_LEFT) //si clic gauche relaché
{
position.x = event.button.x;
position.y = event.button.y;
xTemp2 = tableauX [position.x];
yTemp2 = tableauY [position.y];
x_2 = position.x;
y_2 = position.y;
if (xTemp1 <xTemp2)
{
XDEBUT = xTemp1;
xdebut = x_1;
}
else
{
XDEBUT = xTemp2;
xdebut = x_2;
}
if (yTemp1<yTemp2)
{
YDEBUT = yTemp1;
ydebut = y_1;
}
else
{
YDEBUT = yTemp2;
ydebut = y_2;
}
if (fabs(xTemp1-xTemp2)<fabs(yTemp1-yTemp2))
{
DELTA = fabs(yTemp1-yTemp2);
delta = fabs(y_1-y_2);
}
else
{
DELTA = fabs(xTemp1-xTemp2);
delta = fabs(x_1-x_2);
}
// dessin du cadre blanc pour zoomer dans l'image principale
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE, 1, delta, 32, 0, 0, 0, 0); // Allocation du point
position.x = xdebut ; // Coordonnées du point à placer
position.y = ydebut ;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE,delta, 1, 32, 0, 0, 0, 0); // Allocation du point
position.x = xdebut ; // Coordonnées du point à placer
position.y = ydebut ;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE, 1, delta, 32, 0, 0, 0, 0); // Allocation du point
position.x = xdebut + delta; // Coordonnées du point à placer
position.y = ydebut ;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE, delta, 1, 32, 0, 0, 0, 0); // Allocation du point
position.x = xdebut ; // Coordonnées du point à placer
position.y = ydebut + delta;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
//dessin du cadre dans le mandelbrot témoin
xTemoinDebut = floor(xdebut*deltaTemoin/1050) + xTemoinDebut;
yTemoinDebut = floor(ydebut*deltaTemoin/1050) + yTemoinDebut;
deltaTemoin = floor(delta*deltaTemoin/1050);
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE, 1, deltaTemoin, 32, 0, 0, 0, 0); // Allocation du point
position.x = xTemoinDebut ; // Coordonnées du point à placer
position.y = yTemoinDebut ;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE, deltaTemoin, 1, 32, 0, 0, 0, 0); // Allocation du point
position.x = xTemoinDebut ; // Coordonnées du point à placer
position.y = yTemoinDebut ;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE, 1, deltaTemoin, 32, 0, 0, 0, 0); // Allocation du point
position.x = xTemoinDebut + deltaTemoin; // Coordonnées du point à placer
position.y = yTemoinDebut ;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
rectangle = SDL_CreateRGBSurface(SDL_HWSURFACE, deltaTemoin, 1, 32, 0, 0, 0, 0); // Allocation du point
position.x = xTemoinDebut ; // Coordonnées du point à placer
position.y = yTemoinDebut + deltaTemoin;
SDL_FillRect(rectangle, NULL, SDL_MapRGB(ecran->format, 255,255,255)); // Remplissage du point en gris.
SDL_BlitSurface(rectangle, NULL, ecran, &position); // Collage du point sur l'écran
SDL_Flip(ecran);
SDL_FreeSurface(rectangle);
recalculer = 1;
}
break;
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE)
continuer = 0 ;
if (event.key.keysym.sym == SDLK_r)
{
recommencer = 1 ;
recalculer = 0;
continuer =0;
}
if (event.key.keysym.sym == SDLK_s)
SDL_SaveBMP(ecran , "Mandel_50.bmp" ); // Enregistrement de l'image dans un fichier .bmp
break;
}
}
SDL_FreeSurface(rectangle); // Libération de la surface
}
}
SDL_Quit();
return EXIT_SUCCESS;
}
void petitMandel ()
{
int x=0,y=0;
SDL_Surface *ecran ;
ecran = SDL_GetVideoSurface();
SDL_LockSurface(ecran);
// trait rouge à droite de l'image
for (j=5; j<=1044; j++)
{
x = LARGEUR_ECRAN +5 ;
y = j ;
placerPoint(ecran,x,y,SDL_MapRGB(ecran->format,200,0,0));
}
SDL_Flip(ecran);
// instructions pour placer un petit Mandelbrot témoin dans la fenêtre "interactive"
for ( j = 0 ; j < 600 ; j ++) // balayage vertical
{
yC = YDEBUT + (DELTA * j)/600;
for ( i = 0 ; i < 600 ; i ++) // balayage horizontal
{
xC = XDEBUT + (DELTA * i)/600;
n = 0 ; // initialisation du compteur de calcul
xZ = 0 ;
yZ = 0 ;
xT = 0 ;
while ( xZ*xZ + yZ*yZ < CONST_DIVERGENCE && n < 500) /* boucle de calcul
elle s'arretera si xZ²+yZ² >= 4 ou si on a atteint le maximum d'itérations*/
{
xT = xZ ;// variable temporaire pour le calcul de yZ
xZ = xZ*xZ - yZ*yZ + xC ;
yZ = 2*yZ*xT + yC ;
n ++;
}
if (n< 500)
{
x = i + 1065 ; // Coordonnées du point à placer
y = j + 15;
color = floor (255-255*log(1+n*255/500)/log(256)); // calcul pour un dégradé plus progressif*/
placerPoint(ecran,x,y,SDL_MapRGB(ecran->format,color,color,color));
}
}
}
SDL_UnlockSurface(ecran);
SDL_Flip(ecran);
}
void placerPoint(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
int bpp = surface->format->BytesPerPixel;
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp)
{
case 1:
*p = pixel;
break;
case 2:
*(Uint16 *)p = pixel;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
{
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
}
else
{
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = pixel;
break;
}
}
看起来你在第 309 行额外释放了你的 SDL_Surface 指针 "rectangle" 一次。如果你评论那条线它运行正常。
当代码进入 switch 语句的 "SDL_MOUSEBUTTONUP" 情况时,它释放矩形,然后在第 309 行再次释放它。
你已经完成了运行 tableauX(如果有机会,可能还有 tableauY)。在它们之前放置断言:
assert(j < LARGEUR_ECRAN);
tableauY[j] = yC;
在所有访问前放一个断言(你的程序中有6个)。
我这样做了,但以下断言失败了
assert(position.x < LARGEUR_ECRAN)
xTemp1 = tableauX [position.x];
断言失败意味着 position.x >= LARGEUR_ECRAN。实际上它是1243,而LARGEUR_ECRAN是1050。注意,第一次越界访问不一定会失败,这就是为什么它不会在position.x到达时立即发生1050.
另请注意,在一个系统上 运行 "successfully"(即使存在错误)可能会在另一个系统上崩溃。
编辑:实际上,user5071535 似乎为您的错误消息找到了更有可能的来源,但我可能在这里发现了一个不同的错误。
未分配指针或非 NULL 指针上的每个 free() 都会 return 此错误。在尝试任何 free() 之前,请确认指针是否已分配或等于 NULL。无论如何,任何在未分配的指针或 improperly/insufficient 分配的指针上工作的尝试都会 return 这个错误。在 Windows 下,事情发生的情况有所不同,这只是 "lucky" 的问题:错误的代码将不可避免地在 "random" 时间在任何平台上失败。抱歉英语不好。