最近我在尝试写一个描述机器人比赛场地的代码时,在内存分配上遇到了挂机的问题。代码在Arduino提供的编译平台上全部通过,但是在实际运行时,往往无法跑完测试程序。经过测试发现代码在obstacle对象的构造函数中调用的segajouter(segment tmp)的free(void*ptr)函数中挂机。Arduino使用的是Uno
主题测试程序如下:
#include "ensemble.h"
#include "segment.h"
#include "jonction.h"
#include "obstacle.h"
ensemble set,set2;//结点集合类对象
long x=10,y=45,g=3,h=0;//设置参数
void setup()
{
Serial.begin(115200);
Serial.println(F("Please input a digit:"));
}
void loop()
{
//=====================================================
//Teste de la classe obstacle障碍物类测试
jonction test;
if(Serial.available()>0)
{
Serial.print(F("Free Ram: "));//显示可用内存
Serial.println(freeRam());//显示可用内存
Serial.read();
Serial.print(set2.length());
for(int i=0;i<4;i++)
{
test.set_point(x,y);
test.set_g(g);
test.set_h(h);
x=y-x;
y=g+x;
g=x*g;
h=g-y;
set2.ajouter(test);
Serial.print(F("Free Ram: "));
Serial.println(freeRam());
output(set2.jonc()[i]);//输出读取内容(可能有出入)
//因为添加结点时已经对集合中元素依据f()的大小
//排序
}
Serial.print(F("Free Ram:"));//显示可用内存
Serial.println(freeRam());//显示可用内存
obstacle obs(set2);
Serial.print(F("Free Ram:"));//显示可用内存
Serial.println(freeRam());//显示可用内存
Serial.print(F("NumJonc:"));//输出结点数
Serial.println(obs.NumJonc());
Serial.print(F("NumEdge:"));//输出边数
Serial.println(obs.NumEdge());
set=obs.jonc();
Serial.println(F("Set2:"));
for(int i=0;i<set2.length();i++)//查看set2对象记录的结点
output(set2.jonc()[i]);
Serial.println(F("Set:"));//查看set对象记录的结点
for(int i=0;i<set.length();i++)
output(set.jonc()[i]);
set.vide();//清空set对象
Serial.print(F("Length de set:"));//查看set对象元素个数
Serial.println(set.length());
x=h;//重新设置测试值
y=g;
g=y-x;
h=g/2;
for(int i=0;i<2;i++)
{
test.set_point(x,y);
test.set_g(g);
test.set_h(h);
x=y-x;
y=g+x;
g=y%x;
h=g*x;
set.ajouter(test);//更新set集合
}
Serial.println(F("Set:"));//查看set元素
for(int i=0;i<set.length();i++)
output(set.jonc()[i]);
obstacle ob(set);//创建障碍物对象
if(ob==obs)//检测重载算符==
Serial.println(F("True"));
else
{
Serial.println(F("False"));
ob.reset(set2);//重置ob,使得ob与obs相同
if(ob==obs)//检测重载算符==
Serial.println(F("True"));
else
Serial.println(F("Err"));
}
}
}
//功能函数
void output(jonction test1)//输出结点参数
{
Serial.print(F("(x,y,F,G,H)"));
Serial.print('(');
Serial.print(test1.getx());
Serial.print(',');
Serial.print(test1.gety());
Serial.print(',');
Serial.print(test1.f());
Serial.print(',');
Serial.print(test1.g());
Serial.print(',');
Serial.print(test1.h());
Serial.println(')');
}
long input()//读取输入
{
long n=0;
boolean flag=false;
char ch;
if(Serial.available()>0)
{
ch=Serial.read();
if(ch=='-')
{
flag=true;
delay(2);
ch=Serial.read();
}
n=long(ch-'0');
delay(2);
}
while(Serial.available()>0)
{
ch=Serial.read();
if((ch-'0')<10&&(ch-'0')>=0)
n=10*n+long(ch-'0');
else break;
delay(2);
}
if(flag)
n*=-1;
return n;
}
int freeRam ()//检测可用内存
{
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
类里头是这样定义的:
#include "obstacle.h"
#include "ensemble.h"
#include "segment.h"
#include "stdlib.h"
#include "Arduino.h"
int freeRam1 ()
{
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
void obstacle::segajouter(segment tmp)
//Generer une liste de segment dynamiquement
//n indique le nombre des éléments de *s
{
segment *ss;
n+=1;
Serial.print(F("Hello "));
ss=(segment*)malloc(sizeof(tmp)*n);
if (ss == NULL)
Serial.println(F("malloc failed!"));
for(int i=0;i<n-1;i++)
ss[i]=edge[i];
ss[n-1]=tmp;
// s=(segment*)realloc(edge,n*sizeof(tmp));
Serial.print(F("brave "));
// if(s!=NULL)
// edge=s;
// edge[n-1]=tmp;
free(edge);
Serial.println(F("world!"));
edge=ss;
ss=NULL;
}
obstacle::obstacle(ensemble set)
{
vertex=set;
Serial.print(F("Free Ram: "));
Serial.println(freeRam1());
N=set.length();
n=0;
Serial.println(F("Loop"));
for(int i=0;i<N-1;i++)
for(int j=i+1;j<N;j++)
{
segment tmp(vertex.jonc()[i],vertex.jonc()[j]);
segajouter(tmp);
Serial.print(F("i="));
Serial.print(i);
Serial.print(F(" j="));
Serial.println(j);
Serial.print(F("Free Ram: "));
Serial.println(freeRam1());
}
}
int obstacle::NumJonc()
{
return N;
}
int obstacle::NumEdge()
{
return n;
}
void obstacle::reset(ensemble set)
{
vertex=set;
free(edge);
N=set.length();
n=0;
for(int i=0;i<N-1;i++)
for(int j=i+1;j<N;j++)
{
segment tmp(vertex.jonc()[i],vertex.jonc()[j]);
segajouter(tmp);
}
}
ensemble obstacle::jonc()
{
return vertex;
}
segment* obstacle::Edge()
{
return edge;
}
boolean obstacle::operator ==(obstacle ob)
{
if(ob.jonc().length()==vertex.length()&&ob.jonc().jonc()==vertex.jonc())
return true;
return false;
}
以下是第一次在单片机上跑程序的反馈(由于原注释是部分使用法语的,可能与前面的程序的显示内容有点出入):
Veuillez entrer huit nombres en les séparant par ' ':
Free Ram: 1737
0Free Ram: 1713
(x,y,F,G,H)(10,45,3,3,0)
Free Ram: 1667
(x,y,F,G,H)(35,38,172,105,67)
Free Ram: 1599
(x,y,F,G,H)(3,108,522,315,207)
Free Ram: 1509
(x,y,F,G,H)(105,420,65730,33075,32655)
Free Ram:1509
Free Ram: 1435
Loop
Hello brave world!
i=0 j=1
Free Ram: 1435
Hello brave world!
i=0 j=2
Free Ram: 1435
Hello brave world!
i=0 j=3
Free Ram: 1301
Hello brave world!
i=1 j=2
Free Ram: 1123
Hello brave world!
i=1 j=3
Free Ram: 901
Hello brave world!
i=2 j=3
Free Ram: 901
Free Ram:975
NumJonc:4
NumEdge:6
Set2:
(x,y,F,G,H)(10,45,3,3,0)
(x,y,F,G,H)(35,38,172,105,67)
(x,y,F,G,H)(3,108,522,315,207)
(x,y,F,G,H)(105,420,65730,33075,32655)
Set:
(x,y,F,G,H)(10,45,3,3,0)
(x,y,F,G,H)(35,38,172,105,67)
(x,y,F,G,H)(3,108,522,315,207)
(x,y,F,G,H)(105,420,65730,33075,32655)
Length de set:0
Set:
(x,y,F,G,H)(33390,66780,0,0,0)
(x,y,F,G,H)(0,33390,115621,33390,16695)
Free Ram: 901
Loop
Hello brave world!
i=0 j=1
Free Ram: 901
False
Hello brave world!
He