How to Free All Memory ?
Its possible, or only for to all position and clean one by one ?
Printable View
How to Free All Memory ?
Its possible, or only for to all position and clean one by one ?
Yes it's possible, just keep track of the memory you allocate*... Otherwise no it's not, at least not in the portable sense.
* For example:
Code:void * my_malloc(size_t n)
{
void * ptr = malloc(n);
if(ptr)
{
/* add ptr to an array or linked list or something */
}
return ptr;
}
It is possible for program to use its own memory management routine...
At the start-up program allocates some big regeon using malloc (or something)
Later - it uses only parts of this regeon by calling some home-made alloc/free procedures...
When work is done - the whole regeon is freed - guarantiing that all the memory is returned to the OS
If you meant if there is a function to free all memory you've allocated so far, then no, there isn't.
There are solutions as vart and zacs7 point out, but they do have their own overhead.
Well it's not so hard actually, as long as you know what you're doing and don't care about screwing up libc allocator (never tested it though, but I do not see any reason why it should not).
On UNIX you have brk/sbrk call. Calling sbrk with 0 as argument will give you the pointer to the current heap (top/bottom? depending on arch supposedly). So at the start of the program call sbrk(0), then later at some point call sbrk(0) again, calculate the difference and call sbrk(difference).
Anyway, although it's possible, I'd never do it that way in real application.
To answer the full question in simple terms: No you can't.
A longer answer is:
Assuming there was a way to say "free everything allocated from the heap", you would potentially cause all sorts of problems. Say for example you use "fopen()" to open a file, and you later on call the "magicalfreeeverythingfunction()" - what happens if you call fread() on your file, and the fopen() called malloc to get its internal buffer? If it doesn't go wrong at that point, it almost certainly WILL go wrong when that memory gets allocated for a different reason, because fread() will overwrite the data in the memory you just allocated.
And whilst sergioms's code may not use fopen, fread, etc, it certainly does use library functions that we do not know exactly what the underlying code does. Functions that allocate and free memory arbitrarily are not required to identify themselves in any particular way. So any attempt to free "all memory" without knowing what it represents is almost certain to cause problems.
--
Mats
My Equipment is crazy
I think it not free memory when I Try.
Because, im all alloc and de-alloc, but sometimes it crash.
Example:
in this function, i send a CC (CheckConnection at each 30 s)Code:int VcomCmdUser(TCPREADDATA *p) // Processa as Entradas Recebidas Pelo Usuário. (Obj. Comunicação
{
unsigned int iSckMaxBuffer = 128;
if (p->Length >= 4 && p->Length <= iSckMaxBuffer){ // Pelo Menos 4 Caracteres [STX]XX[13][10]
ProcessaChamado (p->ReadUartChar, p->Length);
ClearStr (p->ReadUartChar);
}
return 1;
}
int ProcessaChamado (unsigned char *pPacote, int pLen){
unsigned char *cFuncao;
unsigned char *cSubFuncao;
unsigned char *cPacote;
int iPosStart, iPosEnd, iPosTam;
cPacote = malloc (pLen);
if (cPacote == NULL)
VcomSendSocket(iUserSocket, "3-ERRO DE ALOCAÇÃO DE MEMÓRIA", 29);
else
//VcomSendSocket(iUserSocket, pPacote, pLen);
//Separa o Pacote
iPosStart = strpos (pPacote, cSTX);
iPosStart++;
iPosEnd = strpos (pPacote, cCR);
iPosTam = iPosEnd - iPosStart;
if((iPosStart >= 0) && (iPosEnd)){
substring(&pPacote[iPosStart], cPacote, iPosTam);
if(strlen (cPacote) > 0){
substring(&cPacote[0], cFuncao, 2);
if (strcmp (cFuncao, "OP") == 0){ // Recebe Ordem de Pesagem
substring(&cPacote[3], cSubFuncao, iPosTam - 2);
OrdemProducao (cSubFuncao);
}
else if (strcmp (cFuncao, "OI") == 0){ // Recebe Ordem de Pesagem Item
substring(&cPacote[2], cSubFuncao, iPosTam - 2);
OrdemProducaoItem (cSubFuncao);
}
else if (strcmp (cFuncao, "OK") == 0){ // Tratamento de Confirmações
substring(&cPacote[2], cSubFuncao, 2);
if (strcmp (cSubFuncao, "OP") == 0) { // Recebe Confirmação de Ordem de Pesagem
EnviaPedidoPC ("OISL", 4);
}
else if (strcmp (cSubFuncao, "OI") == 0){ // Recebe Confirmação de Ordem de Pesagem Item
//if (iItemID == 1){
lPesoTara = lPeso;
iPesaItem = 1;
}
else if (strcmp (cSubFuncao, "IR") == 0){ // Recebe Confirmação de Entrega de Resposta de Item
EnviaPedidoPC ("OISL", 4);
}
}
else if (strcmp (cFuncao, "FI") == 0){ // Recebe Finaliza Item Indicando que Recebeu Todos Itens da OP
iStepInput0 = 0;
iItemID = 0;
iPesaItem = 0;
EnviaPedidoPC ("OPFI", 4);
EscreveDisplay ("ORDEM CONCLUIDA.........................", 3);
}
else if (strcmp (cFuncao, "ER") == 0){ // Erro do Objeto de Comunicação
iStepInput0 = 0;
substring(&cPacote[3], cSubFuncao, iPosTam - 3);
EscreveDisplay (cSubFuncao, 3);
}
else if (strcmp (cFuncao, "CC") == 0){ // Check Connection
// CheckConnection, Não faz nada.
}
else{
// Pacote Não Identitificado;
}
}
else {
free (cPacote);
return 0;
}
}
free (cPacote);
return 1;
}
when i receive some of CC
the program crash and send a message indicate alloc not sucessfull.
That indicates memory corruption - which a "free all" function would not solve.
Get a debugger and start debugging!
I love debug,
but this not a pc
is a icp-i7188E3
and, use a Serial RS-232 to communicate with a balance
a serial 485 to send text to a led display
socket to communicate with a listen socket software
and Digital I/O
when the program crash
it closed all outputs, and no send a message about the error.
I think I've pointed out twice (if not three times) that you are not allocating memory for cFuncao and cSubFuncao [variable names from memory] - you also do not really NEED to use allocation here, fixed size arrays should work perfectly fine.
--
Mats
Well the only way to free all memory is to call exit() (or return from main()...), but I'm guessing you don't actually want to free everything... :D
If by free everything, one only needs to free all handles currently owned by the current process or a certain target process, I do not believe that the question is quite as dangerous nor far-fetched as many have made it sound. Perhaps with a little further explanation as to what purpose this would serve may help us better point you in the right direction.
My gut feeling is that you keep running into issues where your program is eating away a great deal of system resources and your solution is to go ahead and deallocate everything. Thus eliminating the leaked memory handles. If this is the case, you probably should find out why you are leaking so much memory. If not, then if you are doing this in the event that malloc() returns NULL and wish to "free all" to hopefully claim memory resources for your own I would say this is an ill-advised application programming strategy. Considering the fact that your user may have important tasks eating up all the memory you can never assume too much about why the user is out of RAM.
-sphynxster.
Yes, freeing all KNOWN pointers is fine - however, that doesn't actually solve the problem of a memory leak that I'm pretty sure is what sergioms was actually referring to - however, I also think that this is not ACTUALLY the problem in this case - it is a case of abusing memory allocated (or constant data strings) elsewhere.
Also, to "close all known handles" requires that you know what those are.
--
Mats
Very true, some mallocs keep a full table of handles internally though. So its reasonable to say that with a keen enough understanding of the internal data structures used you could theoretically free a handle without knowing what it was. At this point we are no longer talking OS specific, we are talking a specific libc or a specific kernel build. It would be an implimentation so specific it would hardly be worth investigating if the initial issue is indeed a mishandled memory leak. I can only leave it up to sergioms to point us in the direction of what he was trying to do.
My program reset code, to ICP-i7188 sended by the support.Code:#include <conio.h>
#include "..\..\lib\7188e.h"
void (far *Reset_Program)(void)=0xFFFF0000L; //Program start address.
void main(void)
{
InitLib();
Print("Press any ket to begin\n\r");
Print("and press any key can reset the program.\n\r");
Getch();
for(;;)
{
if(Kbhit())
{
Print("7188E have reseted by software.");
DelayMs(10); //Delay 10 ms to wait for all data is sent to COM port.
Reset_Program(); //You can call the function or
//replace it by following 3 asam codes.
//_asm push 0xffff
//_asm push 0
//_asm retf
}
else
Print("*"); //Print '*' while the program is running.
}
}
> but this not a pc
> is a icp-i7188E3
So what part of ProcessaChamado() ABSOLUTELY MUST be run on the target?
I mean, you could (IMO) easily test this on your PC as a console program, by having
and a whole host of other tests.Code:int main ( ) {
printf( "Result=%d\n", ProcessaChamado ("hello", 5) );
}
You can use the debugger to crawl all over it to make sure there are no leaks and no overruns.
By writing functions which don't depend on the target platform at all, you can very easily test them on your PC.
A set of other functions, you can easily write a library of stub functions.
For example, if you've got a target specific LightLED( int id ); function, you can simply create a stub function for the PC which is simply
By the time you get your code on the target, you should have a pretty good idea that 95% of it has already been tested.Code:void LightLED ( int id ) {
printf( "LightLED(%d) called\n", id );
}
Yes but if you do it before certain key areas you may find out the line that's crashing.
ie,
Code:printf("%p\n", (void *) ptr);
ptr->foo = 10;
Like Salem says, you can actually simulate most of these interactions on a PC - there are tools for particularly detecting overruns on memory and such things on the PC, which may not exist on your embedded system, so whilst there is a LITTLE bit of extra work required to get the code working on a PC, you will almost certainly regain all of that and more again by finding logical/memory management problems earlier and easier.
--
Mats
Ok, its function is ok at my ICP, whatever, some times next execute it,
the program send to socket ....... when i try to send OPSL.
The functions actual on ICP:
this function in pc, not is ok, all crazy chars in cDispPacoteCode:void EscreveDisplay (unsigned char *pMensagem, unsigned int pDelaySec){
unsigned char cDispPacote [52];
int iComDisplay = 2;
unsigned int iLims;
unsigned int iLenMsg, iLenCont, iContIndex;
int iBcc;
iDisplaySend = 1;
if (pDelaySec > 0)
Delay(pDelaySec * 1000);
iLims = 46;
cDispPacote [0] = 129;
cDispPacote [1] = 126;
cDispPacote [2] = iLims % 256;
cDispPacote [3] = iLims / 256;
cDispPacote [4] = 1 % 256;
cDispPacote [5] = 1 / 256;
cDispPacote [6] = 0 % 256;
cDispPacote [7] = 0 / 256;
cDispPacote [8] = 76;
cDispPacote [9] = 202;
iLenMsg = strlen (pMensagem);
if (iLenMsg > 40)
iLenMsg = 40;
if (iLenMsg < 40){
for(iLenCont=iLenMsg; iLenCont<40; iLenCont++)
strcat (pMensagem, ".");
}
for(iLenCont=0; iLenCont<40; iLenCont++){
iContIndex = iLenCont + 10;
cDispPacote [iContIndex] = pMensagem [iLenCont];
}
iBcc = cDispPacote [4];
cDispPacote [50] = iBcc;
cDispPacote [51] = '\0';
for(iContIndex=0; iContIndex<=51; iContIndex++){
ToCom (iComDisplay, cDispPacote[iContIndex]);
}
iDisplaySend=0;
}
I try change to this:
Like some this, but in pc is ok, but no in my ICPCode:#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void EscreveDisplay (unsigned char *pMensagem, unsigned int pDelaySec);
void main(void)
{
EscreveDisplay ("SERGIO", 0);
}
void EscreveDisplay (unsigned char *pMensagem, unsigned int pDelaySec){
unsigned char cDispPacote [52];
unsigned int iLims;
unsigned int iLenMsg, iLenCont, iContIndex;
int iBcc;
iLims = 46;
cDispPacote [0] = 129;
cDispPacote [1] = 126;
cDispPacote [2] = iLims % 256;
cDispPacote [3] = iLims / 256;
cDispPacote [4] = 1 % 256;
cDispPacote [5] = 1 / 256;
cDispPacote [6] = 0 % 256;
cDispPacote [7] = 0 / 256;
cDispPacote [8] = 76;
cDispPacote [9] = 202;
iLenMsg = strlen (pMensagem);
for (iLenCont=10; iLenCont<=49; iLenCont++)
cDispPacote [iLenCont] = '.';
for(iLenCont=0; iLenCont<iLenMsg; iLenCont++){
iContIndex = iLenCont + 10;
cDispPacote [iContIndex] = pMensagem [iLenCont];
}
iBcc = cDispPacote [4];
cDispPacote [50] = iBcc;
cDispPacote [51] = '\0';
printf ("Linha 1: \n");
for(iContIndex=0; iContIndex<=51; iContIndex++){
printf ("[%i] %c\n",iContIndex,cDispPacote[iContIndex]);
}
printf ("\n");
getch ();
}
:S
Well, this is definitely WRONG:
[By the way, you don't actually need the if (iLenMsg...) - it is done as part of the for-loop, so you won't enter the loop if it's iLenMsg >= 40.]Code:if (iLenMsg < 40){
for(iLenCont=iLenMsg; iLenCont<40; iLenCont++)
strcat (pMensagem, ".");
}
--
Mats
EscreveDisplay ("LENKE AUTOMACAO", 0);Code:void EscreveDisplay (unsigned char *pMensagem, unsigned int pDelaySec){
unsigned char cDispPacote [52];
int iComDisplay = 2;
unsigned int iLims;
unsigned int iLenMsg, iLenCont, iContIndex;
int iBcc;
iDisplaySend = 1;
if (pDelaySec > 0)
Delay(pDelaySec * 1000);
iLims = 46;
cDispPacote [0] = 129;
cDispPacote [1] = 126;
cDispPacote [2] = iLims % 256;
cDispPacote [3] = iLims / 256;
cDispPacote [4] = 1 % 256;
cDispPacote [5] = 1 / 256;
cDispPacote [6] = 0 % 256;
cDispPacote [7] = 0 / 256;
cDispPacote [8] = 76;
cDispPacote [9] = 202;
iLenMsg = strlen (pMensagem);
for (iLenCont=10; iLenCont<=49; iLenCont++)
cDispPacote [iLenCont] = '.';
for(iLenCont=0; iLenCont<iLenMsg - 1; iLenCont++){
iContIndex = iLenCont + 10;
cDispPacote [iContIndex] = pMensagem [iLenCont];
}
iBcc = cDispPacote [4];
cDispPacote [50] = iBcc;
cDispPacote [51] = '\0';
for(iContIndex=0; iContIndex<=51; iContIndex++){
ToCom (iComDisplay, cDispPacote[iContIndex]);
DelayMs (2);
}
iDisplaySend=0;
}
ok, i had no checked for len, and changed the code.
why this not ok ?
some \0 or like similliar ?
What, exactly, do you get as output? (and what do you expect?)
--
Mats
EscreveDisplay ("LENKE AUTOMACAO", 0);
output need be:
[10 chars prefix (0 to 9)]LENKE AUTOMACAO.........................[BCC][/0]
[0]
[1] ~
[2] .
[3]
[4]
[5]
[6]
[7]
[8] L
[9] Ê
[10] L
[11] E
[12] N
[13] K
[14] E
[15]
[16] A
[17] U
[18] T
[19] O
[20] M
[21] A
[22] C
[23] A
[24] O
[25] .
[26]
[27]
[28] [
[29] %
[30] i
[31] ]
[32]
[33] %
[34] c
[35]
[36]
[37]
[38]
[39]
[40]
[41]
[42] G
[43] #
[44] ;
[45]
[46] Â
[47]
[48] ;
[49]
[50]
[51]
And exactly what code are you using for this - I copied your seconds sample code (the one with main), and adapted it to compile with gcc (remove conio.h and a few other bits like that), and it works just fine.
--
Mats
this code, i has guide by your tips...
Code:#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void EscreveDisplay (unsigned char *pMensagem, unsigned int pDelaySec);
void main(void)
{
// printf("Press any ket to begin\n\r");
// printf("and press any key can reset the program.\n\r");
// getch();
EscreveDisplay ("LENKE AUTOMACAO", 0);
}
void EscreveDisplay (unsigned char *pMensagem, unsigned int pDelaySec){
unsigned char cDispPacote [52];
int iComDisplay = 2;
unsigned int iLims;
unsigned int iLenMsg, iLenCont, iContIndex;
int iBcc;
// iDisplaySend = 1;
// if (pDelaySec > 0)
// Delay(pDelaySec * 1000);
iLims = 46;
cDispPacote [0] = 129;
cDispPacote [1] = 126;
cDispPacote [2] = iLims % 256;
cDispPacote [3] = iLims / 256;
cDispPacote [4] = 1 % 256;
cDispPacote [5] = 1 / 256;
cDispPacote [6] = 0 % 256;
cDispPacote [7] = 0 / 256;
cDispPacote [8] = 76;
cDispPacote [9] = 202;
iLenMsg = strlen (pMensagem);
for(iLenCont=iLenMsg; iLenCont<40; iLenCont++)
strcat (pMensagem, ".");
for(iLenCont=0; iLenCont<40; iLenCont++){
iContIndex = iLenCont + 10;
cDispPacote [iContIndex] = pMensagem [iLenCont];
}
iBcc = cDispPacote [4];
cDispPacote [50] = iBcc;
cDispPacote [51] = '\0';
for(iContIndex=0; iContIndex<=51; iContIndex++){
printf ("[%i] %c\n",iContIndex,cDispPacote[iContIndex]);
// DelayMs (2);
}
printf ("\n");
getch ();
}
This code is _STILL_ very much wrong - because you are modifying a constant variable, and who knows what happens if you do that. On my Windows system, compiling using gcc, I get a immediate crash.Code:for(iLenCont=iLenMsg; iLenCont<40; iLenCont++)
strcat (pMensagem, ".");
If your compiler supports it, you could addto your header - but your compiler may not accept that.Code:const char *pMensagem
--
Mats
i Have changed:
But compiler warning says: Suspicious pointer conversion in this line:Code:void EscreveDisplay (const char *pMensagem, unsigned int pDelaySec){
Code:strcat (pMensagem, ".");
do you believe in the suspect of this a time to process serial receive string ?
I added DelayMs (2) after each of tocom and now, the system seems better, or no... i will test more this..
the serial com is 2400 of baudrate.
15/1/2009 14:00:53 - Rec: ..........................
I had received ......... again, next to escreve () in the function EnviaPedidoPc.
otherwise,
sprintf can fill a specified repeated char in a string ?
like some:
sprintf (pMensagem, "%40c", '.');
There is NOTHING wrong with this code, as far as I can see. strcat or sprintf will definitely be slower an probably take up more code-space too.Code:for (iLenCont=10; iLenCont<=49; iLenCont++)
cDispPacote [iLenCont] = '.';
--
Mats
yes, you're correct,
but here not run andd crash my system,
Or I have some problem and not see
Or this equipment isvery........ing crazy
strcat addd any \0 at end of string?
Not relevant here, I should think.
Figuring out WHY the system crashes is another better idea, I should think.
Yes, strcat() will put a zero on the end of the string - but as I said earlier, you should DEFINITELY NOT modify incoming constant strings (e.g. "Hello, World" passed to your function) - that is DEFINITELY VERY BAD. Never EVER is that right.
It is quite possible that you have other problems similar to this.
--
Mats
I've no idea what the current code looks like.
But anything involving strcat - of either the source or destination strings is broken.
That would be problematic. Test is only a (probably non-null) pointer that points to nowhere.
But why - there is a perfectly fine solution there already which uses the "new" string which you CAN modify. And of course, as Laserlight says, you must either use a char array or allocate some memory (and make sure that's at least 41 bytes, if we use the above strcat() type code).
But I would prefer to not use strcat at all.
--
Mats
I MAKE A TEST WITH THIS CODE:
and call this:Code:void EscreveDisplay (unsigned char *pMensagem, unsigned int pDelaySec){
unsigned char cDispPacote [52];
int iComDisplay = 2;
unsigned int iLims;
unsigned int iLenMsg, iLenCont, iContIndex;
int iBcc;
iDisplaySend = 1;
if (pDelaySec > 0)
Delay(pDelaySec * 1000);
iLims = 46;
cDispPacote [0] = 129;
cDispPacote [1] = 126;
cDispPacote [2] = iLims % 256;
cDispPacote [3] = iLims / 256;
cDispPacote [4] = 1 % 256;
cDispPacote [5] = 1 / 256;
cDispPacote [6] = 0 % 256;
cDispPacote [7] = 0 / 256;
cDispPacote [8] = 76;
cDispPacote [9] = 202;
iLenMsg = strlen (pMensagem);
for (iLenCont=10; iLenCont<=49; iLenCont++)
cDispPacote [iLenCont] = '.';
for(iLenCont=0; iLenCont<iLenMsg; iLenCont++){
iContIndex = iLenCont + 10;
cDispPacote [iContIndex] = pMensagem [iLenCont];
}
iBcc = cDispPacote [4];
cDispPacote [50] = iBcc;
cDispPacote [51] = '\0';
for(iContIndex=0; iContIndex<=51; iContIndex++){
ToCom (iComDisplay, cDispPacote[iContIndex]);
DelayMs (2);
}
iDisplaySend=0;
}
and the resul is ok:Code:void UserCount(void)
{
if (iDisplaySend == 0){
VerificaBotoes ();
if (iVazia)
RecebeSerial ();
if (iPesaItem)
RecebeSerial ();
if (iStepTimer >= 1 && iStepTimer < 10)
iStepTimer++;
}
}
void UserInit(void)
{
unsigned char *MsgDisplay;
InitLib();
PortUser = 5050; // Habilita porta 5050 para Controle do Usuário (Aplicação Objeto de Comunicação (Listener))
// Transforma os Int em Char (ASCII)
cSTX = 2;
cCR = 13;
cLF = 10;
cTab = 9;
IniciaSerial ();
IniciaMemoria();
strcpy (MsgDisplay, "LENKE AUTOMACAO 1");
EscreveDisplay (MsgDisplay, 2);
strcpy (MsgDisplay, "LENKE AUTOMACAO 2");
EscreveDisplay (MsgDisplay, 2);
strcpy (MsgDisplay, "LENKE AUTOMACAO 3");
EscreveDisplay (MsgDisplay, 2);
AddUserTimerFunction(UserCount, 200); // Adiciona Timer para Chamar Função UserCount a cada 200 ms
}
LENKE AUTOMACAO 1................................
LENKE AUTOMACAO 2................................
LENKE AUTOMACAO 3................................
BUT, AFTER THE SYSTEM HAS STOPPPED :\\\\\\\
> unsigned char *MsgDisplay;
> strcpy (MsgDisplay, "LENKE AUTOMACAO 1");
Seriously, learn C before you start messing about with embedded systems.
You're simply making far too many fundamental mistakes to have any success at all.
Embedded systems do not take prisoners, they do not negotiate and they won't tell you a damn thing about where you screwed up.
Whenever you see a * in your code, start paying attention.
Like, answering questions such as
- has it been initialised
- how much memory is it pointing at
- am what I am about to do with that memory OK from an array bounds perspective
Just declaring a pointer, then using it for strcpy takes none of these questions into account, and you get hosed for it.
if i am use:
its compile, run but my program crash at next call to EscreveDisplay...Code:void EscreveDisplay (char pMensagem[17], unsigned int pDelaySec){
// then call by:
char cMsgtest[17];
strcpy (cMsgtest, "LENKE AUTOMACAO");
EscreveDisplay (cMsgtest);
Well, you do not need to specify [17] in the called function, just empty [] will do, or char *.
I do not see why you need to change the code to use strcpy() at all here - that would be the right solution if you update the string that you are passing into EscreveDisplay - but in the code you posted most recently, you are not actually doing that, so it should work fine just passing "LENKE AUTOMACAO" as the input to EscreveDisplay() [obviously with the correct number of parameters].
--
Mats