I am working on a connect-four game simulator in C.
https://en.wikipedia.org/wiki/Connect_Four
The first step is to create a board environment for the game. I went ahead and made a data type board_t which is a struct that includes a dynamically sized array that will save moves played in a single dimension array. Board_t also includes height and width information of the board, so things can be retrieved in a correct manner.
I initialize this board in board_create() function, and use this initialized board_t variable in a board_can_play() function to check whether any play is possible in a given play. Here is the code.
#include <stdlib.h>
#include <assert.h>
#define PLAYER_BLUE 2
#define PLAYER_YELLOW 1
#define PLAYER_EMPTY 0
typedef unsigned char player_t;
typedef struct board_t
{
unsigned int width;
unsigned int height;
unsigned int run;
player_t * moves;
} board_t;
bool board_create (board_t ** b, unsigned int height, unsigned int width, unsigned int run, const player_t * i)
{
//Declare a board_t variable temp_b where parameters will be saved.
board_t temp_b;
//Create a pointer and malloc a memory location based on width and height.
temp_b.moves = malloc(sizeof(unsigned char)*(height*width));
//Itereate through the moves and initialize with the given player_t
int j;
for (j = 0; j < width*height; j++)
{
temp_b.moves[j] = PLAYER_EMPTY;
}
//Input all the values to temp_b
temp_b.height = height;
temp_b.width = width;
temp_b.run = run;
//Make a temporary pointer and assign that pointer to *b.
board_t * temp_b_ptr = malloc(sizeof(board_t));
temp_b_ptr = &temp_b;
*b = temp_b_ptr;
return true;
};
/// Return true if the specified player can make a move on the
/// board
bool board_can_play (const board_t * b, player_t p)
{
unsigned int i;
unsigned int height = board_get_height(b);
unsigned int width = board_get_width(b);
for(i = (height-1)*width; i < height*width; i++)
{
if (b->moves[i] == PLAYER_EMPTY)
{
return true;
}
}
return false;
}
However, whenever I call the board_t *b from board_can_play(), the program gives segmentation fault. More specifically,
if (b->moves[i] == PLAYER_EMPTY)
This line is giving me a segmentation fault. Also, functions that worked well in main(), is not working here in board_can_play(). For instance,
unsigned int height = board_get_height(b);
unsigned int width = board_get_width(b);
Are supposed to get 3 and 3, but getting 2 and 419678? I spent about 7 hours now figuring out, but cannot figure out what is going on.
In the if statement that gives you segfault,
if (b->moves[i] == PLAYER_EMPTY)
The problem is not how moves was allocated, but how b itself was allocated. In board_create(), you are returning a temporary object in here:
board_t * temp_b_ptr = malloc(sizeof(board_t));
temp_b_ptr = &temp_b;
*b = temp_b_ptr;
The malloc'ed pointer is lost (you are overwriting it) and simply returning (through *b) a pointer to a local variable.
So the move the allocation to the top and use temp_b_ptr instead of temp_b:
board_t *temp_b_ptr = malloc(sizeof(board_t));
if( !temp_b_ptr ) {
/* error handling */
}
....
....
*b = temp_b_ptr;
I would approach you problem in the following way. Not that I have stubbed-in some error handling, as well as adding a method to destroy the board when done.
The following code compiles without warning in Ubuntu 14.01 LTS, using gcc-4.8.2. I compile the code with the following command line:
gcc -g -std=c99 -pedantic -Wall connect4.c -o connect4
Now, on to the code. You didn't provide a main, so I created a quick stub main:
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <assert.h>
#define PLAYER_BLUE 2
#define PLAYER_YELLOW 1
#define PLAYER_EMPTY 0
typedef unsigned char player_t;
typedef struct board_t
{
unsigned int width;
unsigned int height;
unsigned int run;
player_t * moves;
} board_t;
bool board_create(board_t** b, unsigned int height, unsigned int width);
void board_destroy(board_t** b);
int board_get_height(const board_t* b);
int board_get_width(const board_t* b);
int main(int argc, char** argv)
{
board_t* pBoard = NULL;
if(board_create(&pBoard, 4, 4))
{
printf("board dimensions: %d by %d\n", board_get_height(pBoard), board_get_width(pBoard));
// TODO : put game logic here...
board_destroy(&pBoard);
}
else
{
fprintf(stderr, "failed to initialize the board structure\n");
}
return 0;
}
Not a lot to see in main, much like you would expect. Next is the board_create
function. Note that I deleted the run and the player_t parameters because i didn't see you use them in your code.
bool board_create(board_t** b, unsigned int height, unsigned int width)
{
bool bRet = false;
if(*b != NULL) // we already have a board struct laying about
{
board_destroy(b);
}
if(NULL != (*b = malloc(sizeof(board_t))))
{
(*b)->width = width;
(*b)->height = height;
if(NULL != ((*b)->moves = malloc(sizeof(unsigned char*)*(height * width))))
{
for(int j = 0; j < height * width; j++)
(*b)->moves[j] = PLAYER_EMPTY;
bRet = true;
}
else
{
/* TODO : handle allocation error of moves array */
}
}
else
{
/* TODO : handle allocation error of board struct */
}
return bRet;
}
Couple of comments on this function;
First a bit of defensive programming, I check to see that the board structure has not be previous allocated. If it was I proceed to destroy the previous board prior to creating a new one. This prevent us leaking memory in that is there was a board allocated and then we recalled this function we would over write the pointer to the original board, and this would mean that we would lose our 'handle' to the first board.
Notice that every call to malloc is check to make sure that we actually got the memory that we wanted. I tend to place the check in the same statement as the malloc, but that is personal preference.
I now actually have a significant return value. In you original code, you would just return true regardless if all the allocations succeeded or not. Notice, that I only return true after both allocations are performed, and they succeeded.
Ok, on the the new function I added, board_destroy:
void board_destroy(board_t** b)
{
if(*b != NULL) // no board struct, nothing to do..
{
if((*b)->moves != NULL)
{
free((*b)->moves);
}
free(*b);
*b = NULL;
}
}
Some comments on this function;
a bit more defensive programming, I check to make sure we actually have a board structure to get rid of prior to doing any work.
remember that in your board structure, you have a dynamic array, so you need to free that array first. (free-ing the board structure first would mean that you lost your only reference to the moves array, and you would be leaking memory then).
Prior to free-ing the moves array, I again check to see that it exists.
Once the moves array is destroyed, I proceed to destroy the board structure, and set the pointer back to NULL (in case we want to reuse the board pointer in main).
You didn't provide implementation details of board_get_* functions, but from their usage, I suspect that you have them implemented as:
int board_get_height(const board_t* b)
{
return (b->height);
}
int board_get_width(const board_t* b)
{
return (b->width);
}
I didn't do anything with your board_can_more function due to not being sure how you intend to use it.
A quick run of the above code:
******#ubuntu:~/junk$ ./connect4
board dimensions: 4 by 4
******#ubuntu:~/junk$
My personal opinion is that when doing lots of memory allocations, frees in C or C++ you should run your program under valgrind periodically to make sure you are not leaking memory or have other memory related errors. Below is a sample of running this code under valgrind:
*****#ubuntu:~/junk$ valgrind --tool=memcheck --leak-check=full ./connect4
==4265== Memcheck, a memory error detector
==4265== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4265== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==4265== Command: ./connect4
==4265==
board dimensions: 4 by 4
==4265==
==4265== HEAP SUMMARY:
==4265== in use at exit: 0 bytes in 0 blocks
==4265== total heap usage: 2 allocs, 2 frees, 152 bytes allocated
==4265==
==4265== All heap blocks were freed -- no leaks are possible
==4265==
==4265== For counts of detected and suppressed errors, rerun with: -v
==4265== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Hope this helps,
T.
Related
I have wrote a small example problem to learn about memory allocation and freeing this memory (to protect from memory leaks):
#include <stdlib.h>
long* foo(char str[]) {
long *nums;
nums = calloc(2,sizeof(long));
//something is happening depending on what's inside the char[]
nums[0] = 57347534;
nums[1] = 84757;
return nums;
}
int main() {
char str1[400] = "This is a test";
long* retValue = foo(str1);
//some lines of checking content of "retValue"
char str2[400] = "This is another test";
retValue = foo(str2);
//some more lines of checking content of "retValue"
char str3[400] = "This is a final test";
retValue = foo(str3);
//again some more lines of checking content of "retValue"
free(retValue);
}
So in my main function, I am using three char arrays which I will pass to my function. This function has a num pointer of long values where am callocing two of them. Then I am just calculating some numbers according to the content in str[] and return nums.
My questions about this are:
How do I free the memory I used for nums? Because I cannot free it before I use it for return.
Is it right to free the retValue in the last line there?
Am I right that I do not need to free my char arrays, because they are not dynamic?
Thanks for your answers, that would help me more safely use pointers!
You need to call free before every new assignment to retValue (if the previous assignment came from malloc, calloc or realloc). Otherwise you will have memory leaks.
Every allocation must be matched by a free, plain and simple.
A good way to answer questions about memory allocation and use is to use a memory checker - I'll use Valgrind:
gcc-8 -std=c11 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds 50627661.c -o 5062766
50627661.c: In function ‘foo’:
50627661.c:3:16: warning: unused parameter ‘str’ [-Wunused-parameter]
long* foo(char str[]) {
~~~~~^~~~~
valgrind -q --leak-check=full ./50627661
==14785== HEAP SUMMARY:
==14785== in use at exit: 32 bytes in 2 blocks
==14785== total heap usage: 3 allocs, 1 frees, 48 bytes allocated
==14785==
==14785== 16 bytes in 1 blocks are definitely lost in loss record 1 of 2
==14785== at 0x4C2EBA5: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14785== by 0x10867F: foo (50627661.c:5)
==14785== by 0x1086F6: main (50627661.c:18)
==14785==
==14785== 16 bytes in 1 blocks are definitely lost in loss record 2 of 2
==14785== at 0x4C2EBA5: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14785== by 0x10867F: foo (50627661.c:5)
==14785== by 0x108758: main (50627661.c:24)
This shows that of the three allocations we made, we only freed one of them - the other two leaked.
If you do not want to clutter your calling code with free, the alternative is to pass to the callee an array mangaged by the caller:
long foo(char str[], long *nums, int size) {
if (size < 2) { // passed array must be at least 2 long
return -1;
}
//something is happening depending on whats inside the char[]
nums[0] = 57347534;
nums[1] = 84757;
return 2; // returns used size (or -1 for error)
}
int main() {
long retValue[2];
char str1[400] = "This is a test";
if (-1 == foo(str1, retValue, 2)) {
// process error condition
}
//some lines of checking content of "retValue"
char str2[400] = "This is another test";
if (-1 == foo(str2, retValue, 2)) {
// process error condition
}
//some more lines of checking content of "retValue"
char str3[400] = "This is a final test";
if (-1 == foo(str3, retValue, 2)) {
// process error condition
}
//again some more lines of checking content of "retValue"
//free(retValue); no need for free since nothing was allocated...
return 0;
}
The problem is that my code is not so small so I will post only fragments of it, let me know if more of it is needed for the question to be valid.
The program uses library with various sorting algorithms (18 of them), and applies them to an unsorted array. User can select array size and how many arrays will be tested.
If I select, for example, 100arrays of 1000 elements (18*100 = 1800 times algorithms sort the array), the code works. If it is the other way, ie 1000 arrays of say 10 elements, 1000 * 18 = 18 000 sortings, then it crashes with "double free or corruption".
The question is not as much as where the problem lies, but firstly, how to debug it correctly.
Here is the function which gets a function pointer (func) of sorting algorithm, sorts the elements, checks if sorted, adds appropriate data to
"Iteration" struct, and then frees both "target" (array to be sorted) and "Iter" (Iterations struct).
void test_sort(int* data, int size, sort_pointer func, Algorithm* Algo, int no)
{
count_ncomp = 0;
count_assign = 0;
begin = clock();
int* target = NULL;
target = malloc(size * sizeof(int));
if (!target)
die("Memory error.");
memcpy(target, data, size * sizeof(int));
Iteration* Iter = malloc(sizeof(Iteration));
Iter->no = no;
if (is_sorted(func(target, size), size)) {
end = clock();
clocks = (double)(end - begin);
time_spent = clocks / CLOCKS_PER_SEC;
Iter->is_sorted = 1;
Iter->comp_count = count_ncomp;
Iter->assign_count = count_assign;
Iter->clocks_total = clocks;
Iter->time_spent = time_spent;
} else {
Iter->is_sorted = 0;
debug("Not sorted, no: %d", no);
};
Algo->iterations[no - 1] = Iter;
if (target == NULL) {
debug("Target is NULL");
}
debug("before target1 free");
debug("NO: %d", no);
debug("pointer %p", target);
free(target);
free(Iter);
debug("after target1 free");
/*target = NULL;*/
}
Here is the list of data structures:
typedef struct {
int no;
int is_sorted;
int comp_count;
int assign_count;
double clocks_total;
double time_spent;
} Iteration;
typedef struct {
char* type;
char* complexity;
int iter_count;
int rank;
int avg_comp;
int avg_assign;
double avg_clocks;
double avg_time;
Iteration* iterations[MAX_ITER];
} Algorithm;
Here is the start of the program:
Starting program: /home/riddle/tmp1/pratybos12
Mem used total: 0
How many arrays would you like to test? > 1000
What is the size of each array? > 10
What is the minimum number in each array? > 1
What is the maximum number in each array? > 10
How many repeating values there will be AT LEAST? > 0
Here is the running program:
DEBUG pratybos12.c:537: NO: 374
DEBUG pratybos12.c:538: pointer 0x55899fe8cb10
*** Error in `./pratybos12': double free or corruption (out): 0x000055899fe8cae0 ***
[1] 3123 abort (core dumped) ./pratybos12
GDB output (I get a crash always on no=374):
DEBUG pratybos12.c:542: after target1 free
DEBUG pratybos12.c:535: before target1 free
DEBUG pratybos12.c:537: NO: 374
DEBUG pratybos12.c:538: pointer 0x555555760b10
Breakpoint 1, test_sort (data=0x555555760ab0, size=10, func=0x555555558c04 <bubble_sort_b_and_c_and_e_and_f>, Algo=0x55555575ff00, no=374) at pratybos12.c:541
541 free(Iter);
(gdb) print Iter
$3 = (Iteration *) 0x555555760ae0
(gdb) c
Continuing.
*** Error in `/home/riddle/tmp1/pratybos12': double free or corruption (out): 0x0000555555760ae0 ***
Program received signal SIGABRT, Aborted.
0x00007ffff7a54860 in raise () from /usr/lib/libc.so.6
I've read many posts suggesting testing it with Valgrind, however, running with Valgrind, this crash does not arise.
I know that I have posted very little info, please keep me updated to what more is needed.
The main question is how to debug. How do I check if the pointer before freeing points to something valid, is the memory accessible, etc.
These two lines from the function:
Algo->iterations[no - 1] = Iter;
...
free(Iter);
First you make Algo->iterations[no - 1] point to the same memory that Iter is pointing two, so you have two pointers pointing to the same memory. Then you free the memory, making both pointers invalid.
If you want to use the pointer later you can't free it.
Windows has triggered a breakpoint in Graph.exe.
This may be due to a corruption of the heap, which indicates a bug in Graph.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while Graph.exe has focus.
The output window may have more diagnostic information
I don't have any breakpoint in my code and I don't pressed F12.
this is my code.
what's wrong?
printf("sizeof edge : %d\n",sizeof(edge));this line make that error.
I can't understand why
what's wrong?
#include <stdio.h>
#include <stdlib.h>
typedef struct HeapStruct heap;
typedef struct edge edge;
struct edge
{
int start,end,weight;
};
struct HeapStruct {
int Capacity;
int Size;
edge *head;
};
void init(int * sets,int size);
int unionsets(int * sets, int i, int j);
int find(int * sets, int i);
void buildHeap(heap h);
edge deleteMin(heap * h);
int ends(int * sets,int size);
int main()
{
int V,E,*sets,a,startv,endv,weight;
char c,h;
edge ed;
edge * ee;
heap * Heap;
Heap = (heap*)malloc(sizeof(heap));
printf("sizeof edge : %d\n",sizeof(edge));//this line
scanf("%d",&V);
sets = (int*)malloc(sizeof(int)*V);
init(sets,V);
scanf("%d",&E);
Heap->head = (edge*)malloc(sizeof(edge)*E);//and this line
Heap->Capacity = E;
Heap->Size=0;
for(a=0; a<E; a++)
{
scanf("%d%c%d%c%d",&startv,&c,&endv,&h,&weight);
Heap->head[Heap->Size].end = endv;
Heap->head[Heap->Size++].start = startv;
Heap->head[Heap->Size++].weight = weight;
}
buildHeap(*Heap);
do
{
ed = deleteMin(Heap);
if(find(sets,ed.start)<0 || find(sets,ed.end)<0 || find(sets,ed.start) != find(sets,ed.end))
{
unionsets(sets,ed.start,ed.end);
printf("%d,%d,%d\n",ed.start,ed.end,ed.weight);
}
}
while(ends(sets,V));
scanf("%d%c%d%c%d",&startv,&c,&endv,&h,&weight);
return 0;
}
Windows has triggered a breakpoint in Graph.exe.
It is literally what it says, the operating system itself made the debugger stop. When you debug your program on any recent Windows version then you get the debug version of the Windows memory manager. Which adds extra checks that ensure that your program isn't corrupting the heap. When it detects heap damage then it breaks the program to tell you about it.
Very useful. What you need to do next is to carefully review your code to make sure it isn't writing to memory that wasn't allocated. You'll then land on this statement:
Heap->head[Heap->Size++].start = startv;
Which along with the other statements in that code assumes that this array contains 3 * E elements but you allocated only E elements.
Kaboom!
printf("sizeof edge : %d\n",sizeof(edge));
This can crash a 64-bit system, because sizeof returns a 64-bit number but %d expects only 32 bits. Try %zd instead.
Yep, C is finicky. Your compiler should have given a warning about this, though.
I am attempting to tackle college worksheet on C programming (no marking for it, just to improve our learning). What we're meant to do is get a few details about shipping docks. I decided to use structures for this.
My code is below, what I need help with is to print out the information (to see if its working) of whats at the location of the shipyards .run.
Everything compiles and according to the debugger shipyard1.run and shipyard2.run point to different locations, but I can not see the values.
int main(int argc, char** argv)
{
typedef struct dockInfo
{
int dockCode;
int dockLength;
}dckDetails;
typdef struct shipyard
{
char dockName[20];
/* however big this number is thats how many dockInfo structs are needed.*/
int numOfDocks;
dckDetails *run; //points to the array of dockInfo structs
};
struct dockInfo *arrayD; // the array to hold all the dockInfo structs
struct dockInfo tempo; // the temporary dockInfo struct to take in the details
struct shipyard shipyard1;
struct shipyard shipyard2;
/**
* the variables for shipyard1 and shipyard2 are then assigned
**/
int i;
for (i=0;i<shipyard1.numOfDocks;i++)
{
arrayD=calloc(shipyard1.numOfDocks,100); // allocate a new bit of memory for arrayD
tempo.dockCode=45*i;
tempo.dockLength=668*i;
arrayD[i]=tempo; //the element of arrayD becomes tempo.
}
shipyard1.run=arrayD; //make shipyard1.run point to the location of arrayD.
for (i=0;i<shipyard2.numOfDocks;i++)
{
arrayD=calloc(shipyard2.numOfDocks,100); // allocate a new bit of memory for arrayD
tempo.dockCode=1234*i;
tempo.dockLength=1200*i;
arrayD[i]=tempo; //the element of arrayD becomes tempo.
}
shipyard2.run=arrayD; //make shipyard2.run point to the new location of arrayD.
int elementTest1; // need element1test to be shipyard1.run[0].dockLength;
int elementTest2; // need element2test to be shipyard2.run[1].dockCode;
return (EXIT_SUCCESS);
}
It should be noted that I have left a lot of code out because I have yet to write it. I have used static examples for the moment (shipyard1 and shipyard2) but in the future I am going to implment a 'load info from file' feature.
Any help would be greatly appreciated and please excuse my English if it's poor, English is not my first language.
You have calloc() inside a for loop twice. Both times you're losing the address returned.
for () {
addr = calloc();
addr[i] = ...
}
the second time through the loop, the addr you got on the first time is gone (you got yourself a memory leak), the value you saved there is gone too.
Move the calloc() outside the loop ... and remember to free() the memory when you no longer need it
addr = calloc();
for () {
addr[i] = ...
}
free(addr);
Some feedback:
The memory allocation parts with calloc should occur outside the loop. Now you allocate it, and then loose track of it in the next iteration because new memory is allocated and assigned.
memory you allocate should be freed somewhere with free
shipyard1.numOfDocks (same for shipyard2) is unitialized when you use it, it may be a random number (which means you have an undefined number of loop iterations, and allocate an undefined amount of memory).
Good luck!
Others have made some very good points, and you should fix your code according to them. So far, no one seems to have seen that the call to calloc() is wrong. Instead of:
arrayD=calloc(shipyard1.numOfDocks,100);
it should be:
arrayD = calloc(shipyard1.numOfDocks, sizeof *arrayD);
You want shipyard1.numOfDocks objects, each of size equal to sizeof *arrayD.
In fact, as mentioned below, you don't need to set the memory allocated to all-zeros, so you can replace calloc() by malloc():
arrayD = malloc(shipyard1.numOfDocks * sizeof *arrayD);
(Be sure to #include <stdlib.h>, whether you call calloc() or malloc().)
I have some minor comments about style:
you don't need the typedef. You can write struct dockInfo instead of dckDetails. If you do keep the typedef, you should be consistent, and use the typedef name everywhere. You use struct dockInfo most of the time, and then use dckDetails once. Your usage suggests that you probably weren't comfortable declaring a pointer to the struct. However, struct dockInfo *run is a completely valid declaration.
you don't need the tempo object. You can instead do: arrayD[i].dockCode = 45*i; arrayD[i].dockLength = 668*i;
Unless you're running C99, you can't declare variables after statements in a block. So you should move the declarations for elementTest1 and elementTest2 to the top of main(), with other declarations.
return is a statement, not a function, so the parentheses are not needed.
Since you overwrite the memory allocated immediately, and don't need it to be zero, you can replace calloc() call by a suitable call to malloc().
As I said, these are minor comments. Your main problems lie with the wrong use of calloc, etc.
I shortened the variable names and re-wrote this to do what I think you are interested in. I also added display of the addresses the data is stored in.
Generally, when I try to understand something in the arrays and pointers world, I make the simple case work - an embedded array (my yard1) and then do the pointer thing after that (yard2, yard3)
You'll note each set of data has different start points, two add i for each point, one multiplies by i for each point.
#include <libc.h>
#include <stdlib.h>
#include <stdio.h>
#define MAX_DOCKS 100
int main(int argc, char** argv)
{
struct dock
{
int code;
int length;
};
struct yard
{
char name[20];
int numDocks;
struct dock arDocks[MAX_DOCKS]; //an array of dock structs
};
struct yard_2
{
char name[20];
int numDocks;
struct dock *run; //points to the array of dock structs
};
/* data within main function */
struct dock *arrayD; // pointer to dock structs
struct yard yard1;
struct yard_2 yard2;
struct yard_2 yard3;
int i;
char temp[] = "2 draY";
strcpy( yard2.name, temp ); /* temp is only persistant in main... */
strcpy( yard1.name, "Yard 1");
strcpy( yard3.name, "3 y 3 a 3 r 3 d 3");
yard1.numDocks = MAX_DOCKS; /* or so I guess.. */
yard2.numDocks = MAX_DOCKS; /* or so I guess.. */
yard3.numDocks = MAX_DOCKS; /* or so I guess.. */
/* get some memory, init it to 0 */
arrayD = calloc( yard2.numDocks, sizeof( struct dock ) );
/* connect to the yard2 struct via "run", a pointer to struct dock */
yard2.run = arrayD;
/* without middleman... get more memory, init it to 0 */
yard3.run = calloc( yard3.numDocks, sizeof( struct dock ) );
/* at this point arrayD could be re-used to get another hunk.. */
/* fill in and display data .. */
for (i=0;i<yard1.numDocks;i++)
{
/* This sets all the memory for yard 1... */
yard1.arDocks[i].code = 45 + i;
yard1.arDocks[i].length = 668 + i;
/* so here are some ways to display the data */
printf("%d, %d %x %d %x - ",
i, yard1.arDocks[i].code, &(yard1.arDocks[i].code),
(yard1.arDocks[i].length), &(yard1.arDocks[i].length) );
/* This sets the memory for yard 2... */
yard2.run[i].code = 45 * i;
yard2.run[i].length = 668 * i;
/* Display through a pointer to a calloc'ed array of structs is the
same syntax as the embedded array of structs. The addresses of the
array are completely different - 0xbffff704 vs 0x800000 on my Intel-based iMac... */
printf("%d %x %d %x - ",
yard2.run[i].code, &(yard2.run[i].code),
yard2.run[i].length, &(yard2.run[i].length) );
yard3.run[i].code = 100 + i;
yard3.run[i].length = 2000 + i;
/* see where second calloc got its memory... */
printf("%d %x %d %x\n",
yard3.run[i].code, &(yard3.run[i].code),
yard3.run[i].length, &(yard3.run[i].length) );
}
/* data all filled in, more demos of how to get it back: */
printf( "%s, : 1\n", yard1.name );
printf( "%d, : numOfDocs \n", yard1.numDocks );
printf( "0x%x, : arDocks \n", yard1.arDocks );
int elementTest1 = yard1.arDocks[0].length;
int elementTest2 = yard1.arDocks[1].code;
int elementTest3 = yard2.run[0].length;
int elementTest4 = yard3.run[1].code;
printf( "elementTest1: yard1.arDocks[0].length %d\n", elementTest1 );
printf( "elementTest2: yard1.arDocks[1].code %d\n", elementTest2 );
printf( "elementTest3: yard2.run[0].length %d\n", elementTest3 );
printf( "elementTest4: yard3.run[1].code; %d\n", elementTest4 );
for (i=0; i< yard2.numDocks; i++ ) {
printf("%d %d %d _ ", i, yard2.run[i].length, yard2.run[i].code);
printf(" %d %d \n", yard3.run[i].length, yard3.run[i].code);
}
return (EXIT_SUCCESS);
}
Here's an edited example of the output, compile/build via cc, cmd line a.out:
Macintosh-6:interview Bill4$ cc
dockyard.c Macintosh-6:interview
Bill4$ a.out
0 45 bffff6f8 668 bffff6fc - 0 800000 0 800004 - 100 800400 2000 800404
1 46 bffff700 669 bffff704 - 45 800008 668 80000c - 101 800408 2001 80040c
2 47 bffff708 670 bffff70c - 90 800010 1336 800014 - 102 800410 2002 800414
:
Yard 1, : 1
100, : numOfDocs
0xbffff6f8, : arDocks
elementTest1: yard1.arDocks[0].length 668
elementTest2: yard1.arDocks[1].code 46
elementTest3: yard2.run[0].length 0
elementTest4: yard3.run[1].code; 101
0 0 0 _ 2000 100
1 668 45 _ 2001 101
2 1336 90 _ 2002 102
3 2004 135 _ 2003 103
:
99 66132 4455 _ 2099 199
Macintosh-6:interview Bill4$
programming language: C
platform: ARM
Compiler: ADS 1.2
I need to keep track of simple melloc/free calls in my project. I just need to get very basic idea of how much heap memory is required when the program has allocated all its resources. Therefore, I have provided a wrapper for the malloc/free calls. In these wrappers I need to increment a current memory count when malloc is called and decrement it when free is called. The malloc case is straight forward as I have the size to allocate from the caller. I am wondering how to deal with the free case as I need to store the pointer/size mapping somewhere. This being C, I do not have a standard map to implement this easily.
I am trying to avoid linking in any libraries so would prefer *.c/h implementation.
So I am wondering if there already is a simple implementation one may lead me to. If not, this is motivation to go ahead and implement one.
EDIT: Purely for debugging and this code is not shipped with the product.
EDIT: Initial implementation based on answer from Makis. I would appreciate feedback on this.
EDIT: Reworked implementation
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <limits.h>
static size_t gnCurrentMemory = 0;
static size_t gnPeakMemory = 0;
void *MemAlloc (size_t nSize)
{
void *pMem = malloc(sizeof(size_t) + nSize);
if (pMem)
{
size_t *pSize = (size_t *)pMem;
memcpy(pSize, &nSize, sizeof(nSize));
gnCurrentMemory += nSize;
if (gnCurrentMemory > gnPeakMemory)
{
gnPeakMemory = gnCurrentMemory;
}
printf("PMemAlloc (%#X) - Size (%d), Current (%d), Peak (%d)\n",
pSize + 1, nSize, gnCurrentMemory, gnPeakMemory);
return(pSize + 1);
}
return NULL;
}
void MemFree (void *pMem)
{
if(pMem)
{
size_t *pSize = (size_t *)pMem;
// Get the size
--pSize;
assert(gnCurrentMemory >= *pSize);
printf("PMemFree (%#X) - Size (%d), Current (%d), Peak (%d)\n",
pMem, *pSize, gnCurrentMemory, gnPeakMemory);
gnCurrentMemory -= *pSize;
free(pSize);
}
}
#define BUFFERSIZE (1024*1024)
typedef struct
{
bool flag;
int buffer[BUFFERSIZE];
bool bools[BUFFERSIZE];
} sample_buffer;
typedef struct
{
unsigned int whichbuffer;
char ch;
} buffer_info;
int main(void)
{
unsigned int i;
buffer_info *bufferinfo;
sample_buffer *mybuffer;
char *pCh;
printf("Tesint MemAlloc - MemFree\n");
mybuffer = (sample_buffer *) MemAlloc(sizeof(sample_buffer));
if (mybuffer == NULL)
{
printf("ERROR ALLOCATING mybuffer\n");
return EXIT_FAILURE;
}
bufferinfo = (buffer_info *) MemAlloc(sizeof(buffer_info));
if (bufferinfo == NULL)
{
printf("ERROR ALLOCATING bufferinfo\n");
MemFree(mybuffer);
return EXIT_FAILURE;
}
pCh = (char *)MemAlloc(sizeof(char));
printf("finished malloc\n");
// fill allocated memory with integers and read back some values
for(i = 0; i < BUFFERSIZE; ++i)
{
mybuffer->buffer[i] = i;
mybuffer->bools[i] = true;
bufferinfo->whichbuffer = (unsigned int)(i/100);
}
MemFree(bufferinfo);
MemFree(mybuffer);
if(pCh)
{
MemFree(pCh);
}
return EXIT_SUCCESS;
}
You could allocate a few extra bytes in your wrapper and put either an id (if you want to be able to couple malloc() and free()) or just the size there. Just malloc() that much more memory, store the information at the beginning of your memory block and and move the pointer you return that many bytes forward.
This can, btw, also easily be used for fence pointers/finger-prints and such.
Either you can have access to internal tables used by malloc/free (see this question: Where Do malloc() / free() Store Allocated Sizes and Addresses? for some hints), or you have to manage your own tables in your wrappers.
You could always use valgrind instead of rolling your own implementation. If you don't care about the amount of memory you allocate you could use an even simpler implementation: (I did this really quickly so there could be errors and I realize that it is not the most efficient implementation. The pAllocedStorage should be given an initial size and increase by some factor for a resize etc. but you get the idea.)
EDIT: I missed that this was for ARM, to my knowledge valgrind is not available on ARM so that might not be an option.
static size_t indexAllocedStorage = 0;
static size_t *pAllocedStorage = NULL;
static unsigned int free_calls = 0;
static unsigned long long int total_mem_alloced = 0;
void *
my_malloc(size_t size){
size_t *temp;
void *p = malloc(size);
if(p == NULL){
fprintf(stderr,"my_malloc malloc failed, %s", strerror(errno));
exit(EXIT_FAILURE);
}
total_mem_alloced += size;
temp = (size_t *)realloc(pAllocedStorage, (indexAllocedStorage+1) * sizeof(size_t));
if(temp == NULL){
fprintf(stderr,"my_malloc realloc failed, %s", strerror(errno));
exit(EXIT_FAILURE);
}
pAllocedStorage = temp;
pAllocedStorage[indexAllocedStorage++] = (size_t)p;
return p;
}
void
my_free(void *p){
size_t i;
int found = 0;
for(i = 0; i < indexAllocedStorage; i++){
if(pAllocedStorage[i] == (size_t)p){
pAllocedStorage[i] = (size_t)NULL;
found = 1;
break;
}
}
if(!found){
printf("Free Called on unknown\n");
}
free_calls++;
free(p);
}
void
free_check(void) {
size_t i;
printf("checking freed memeory\n");
for(i = 0; i < indexAllocedStorage; i++){
if(pAllocedStorage[i] != (size_t)NULL){
printf( "Memory leak %X\n", (unsigned int)pAllocedStorage[i]);
free((void *)pAllocedStorage[i]);
}
}
free(pAllocedStorage);
pAllocedStorage = NULL;
}
I would use rmalloc. It is a simple library (actually it is only two files) to debug memory usage, but it also has support for statistics. Since you already wrapper functions it should be very easy to use rmalloc for it. Keep in mind that you also need to replace strdup, etc.
Your program may also need to intercept realloc(), calloc(), getcwd() (as it may allocate memory when buffer is NULL in some implementations) and maybe strdup() or a similar function, if it is supported by your compiler
If you are running on x86 you could just run your binary under valgrind and it would gather all this information for you, using the standard implementation of malloc and free. Simple.
I've been trying out some of the same techniques mentioned on this page and wound up here from a google search. I know this question is old, but wanted to add for the record...
1) Does your operating system not provide any tools to see how much heap memory is in use in a running process? I see you're talking about ARM, so this may well be the case. In most full-featured OSes, this is just a matter of using a cmd-line tool to see the heap size.
2) If available in your libc, sbrk(0) on most platforms will tell you the end address of your data segment. If you have it, all you need to do is store that address at the start of your program (say, startBrk=sbrk(0)), then at any time your allocated size is sbrk(0) - startBrk.
3) If shared objects can be used, you're dynamically linking to your libc, and your OS's runtime loader has something like an LD_PRELOAD environment variable, you might find it more useful to build your own shared object that defines the actual libc functions with the same symbols (malloc(), not MemAlloc()), then have the loader load your lib first and "interpose" the libc functions. You can further obtain the addresses of the actual libc functions with dlsym() and the RTLD_NEXT flag so you can do what you are doing above without having to recompile all your code to use your malloc/free wrappers. It is then just a runtime decision when you start your program (or any program that fits the description in the first sentence) where you set an environment variable like LD_PRELOAD=mymemdebug.so and then run it. (google for shared object interposition.. it's a great technique and one used by many debuggers/profilers)