Here are the related structs:
typedef struct OS_BM {
void *free; /* Pointer to first free memory block */
void *end; /* Pointer to memory block end */
U32 blk_size; /* Memory block size */
U32 owner_one;
} *P_BM;
typedef struct NEW { //struct ADDED BY ME
void *free;
U8 pid;
} *P_GH;
Here is the code in question (only the part "ADDED BY ME"):
void *rt_alloc_box (void *box_mem) {
/* Allocate a memory block and return start address. */
void **free;
#if !(defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M))
int irq_dis;
irq_dis = __disable_irq ();
free = ((P_BM) box_mem)->free;
if (free) {
array[counter]->free=((P_BM) box_mem)->free; //ADDED BY ME- MAY NOT BE WORKING
array[counter]->pid = rt_tsk_self(); //ADDED BY ME
counter++; //ADDED BY ME
((P_BM) box_mem)->free = *free;
}
if (!irq_dis) __enable_irq ();
#else
do {
if ((free = (void **)__ldrex(&((P_BM) box_mem)->free)) == 0) {
__clrex();
break;
}
} while (__strex((U32)*free, &((P_BM) box_mem)->free));
#endif
return (free);
}
int free_owner (void *box_mem, void *box){ //FUNCTION ADDED BY ME
int i;
for(i = 0; i<8;i++){
if (box == array[i]->free;){ //MAY NOT BE WORKING
if(rt_tsk_self() == (array[i]->pid))
return (0);
}
}
return (1);
}
Code Description: The first function is to do with memory allocation, but I need to added protection/ownership to the memory block that is allocated from the pool. That is why I am putting the memory block address as well as the process ID (returned from rt_tsk_self()) into an extra global array that I created. The second function just checks if the process with using the allocated block has the same ownership as the one created (again it uses rt_tsk_self()).
Actual Problem: The lines commented with "MAY NOT BE WORKING" don't seem to work as I am sure that I can put the process ID into the array as well as checking that it is in there, but I cannot do the same with memory block address. This is very likely to just be a simple coding error rather than conceptual.
if (box == array[i]->free;){ //MAY NOT BE WORKING
Shouldn't this be:
if (box == *(array[i]->free)){ //MAY NOT BE WORKING
Also, somehow comparing void pointers make me, uneasy.
Related
I'm trying to use a "fixed memory scheme" and pre-allocate memory & reuse it via alloc, init, free fashion as many times as possible.
free() will called at shutdown only, but I want to test many iterations.
Although I call my alloc function bn_tree_alloc_node_space_heap() & init function bn_tree_init_node_heap(), I can only call free function bn_tree_free_node_space once.
Below is a complete reproducible snippet of my memory management, maint_test.c:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <float.h>
#define BN_TREE_HEAP_SIZE 100
/*variables internal*/
typedef struct bntree_internals;
/*bn_tree_node is single bntree_t leaf*/
typedef struct bn_tree_node {
struct bn_tree_node* left;
struct bn_tree_node* right;
float* dataset;
float distance_to_neighbor;
int visited;
int heap_index;
} bn_tree_node;
/*tree*/
typedef struct {
/*in order to keep track of the bn-tree root*/
bn_tree_node* _root;
/*pointer to internal variables struct*/
struct bntree_internals* _internals;
} bntree_t;
/*bn tree leaf nodes heap*/
bn_tree_node* node_processing_space = NULL;
/*leaf nodes*/
void bn_tree_alloc_node_space_heap(int max_dimensions);
bn_tree_node*
get_pre_allocated_bn_tree_node_heap();
void bn_tree_init_node_heap(bn_tree_node* nodes, int max_dimensions);
void bn_tree_free_node_space(bn_tree_node* nodes);
int main(int argc, char** argv) {
/*PROBLEM:called the alloc,init,free cycle several times, problem,
getting seg fault on 2nd call of free()*/
bn_tree_alloc_node_space_heap(3);
assert(get_pre_allocated_bn_tree_node_heap());
printf("alloc\n");
bn_tree_init_node_heap(node_processing_space, 3);
printf("init\n");
bn_tree_free_node_space(node_processing_space);
printf("free\n");
bn_tree_alloc_node_space_heap(3);
assert(get_pre_allocated_bn_tree_node_heap());
printf("alloc\n");
bn_tree_init_node_heap(node_processing_space, 3);
printf("init\n");
bn_tree_free_node_space(node_processing_space);
printf("free\n");
bn_tree_alloc_node_space_heap(3);
assert(get_pre_allocated_bn_tree_node_heap());
printf("alloc\n");
bn_tree_init_node_heap(node_processing_space, 3);
printf("init\n");
bn_tree_free_node_space(node_processing_space);
printf("free\n");
bn_tree_alloc_node_space_heap(3);
assert(get_pre_allocated_bn_tree_node_heap());
printf("alloc\n");
bn_tree_init_node_heap(node_processing_space, 3);
printf("init\n");
bn_tree_free_node_space(node_processing_space);
printf("free\n");
return (EXIT_SUCCESS);
}
void bn_tree_alloc_node_space_heap(int max_dimensions) {
if (NULL == node_processing_space) {
node_processing_space = (bn_tree_node*) calloc(BN_TREE_HEAP_SIZE, sizeof (bn_tree_node));
//TODO: bn_tree_set_k_dimensions (max_dimensions);
int i = 0;
for (; i < BN_TREE_HEAP_SIZE; i++) {
node_processing_space[i].dataset = (float*) calloc(max_dimensions, sizeof (float));
}
//bn_heap_tail_index = bn_heap_head_index = 0;
}
}
bn_tree_node* get_pre_allocated_bn_tree_node_heap() {
return node_processing_space;
}
void bn_tree_init_node_heap(bn_tree_node* nodes, int max_dimensions) {
int i = 0;
int c = 0;
for (; i < BN_TREE_HEAP_SIZE; i++) {
/*reset values */
if (NULL != nodes[i].dataset) {
c = 0;
for (; c < max_dimensions; c++) {
nodes[i].dataset[c] = FLT_MIN;
}
}
nodes[i].visited = 0;
nodes[i].distance_to_neighbor = FLT_MAX;
nodes[i].left = NULL;
nodes[i].right = NULL;
nodes[i].heap_index = -1;
}
}
/*PROBLEM is subsequent call to free(), but if I alloc again why cant I free again?*/
void bn_tree_free_node_space(bn_tree_node* nodes) {
int i = 0;
for (; i < BN_TREE_HEAP_SIZE; i++) {
if (nodes[i].dataset) {
free(nodes[i].dataset);
}
}
free(nodes);
nodes = NULL;
}
Here is the output that I expect/want:
alloc
init
free
alloc
init
free
alloc
init
free
alloc
init
free
But Im getting this output/error:
alloc
init
free
alloc
init
double free or corruption (!prev)
Aborted (core dumped)
How can fix this?
Can't I do alloc,init,free as many times as I want (as long as I called alloc before free) OR I can do only alloc() once, then many init(), free() once?
Thanks a million & please be kind enough to provide concise answers with minimal changes.
The problem is that your bn_tree_free_node_space function takes, as its argument, a copy of the pointer variable - that is, you are passing the pointer by value - thus, the line nodes = NULL; at the end of that function only sets the local variable to NULL and does not change the value of the node_processing_space variable.
To fix this (with minimal changes to your code logic1), you need to pass that function a pointer to the pointer, and dereference that in the function. So, your function should look like this:
void bn_tree_free_node_space(bn_tree_node** nodes) // Argument is pointer-to-pointer
{
int i = 0;
for (; i < BN_TREE_HEAP_SIZE; i++) {
if ((*nodes)[i].dataset) { // Now we need to use (*nodes) to get the underlying pointer
free((*nodes)[i].dataset); // ... same here
}
}
free(*nodes); /// ... and here
*nodes = NULL;
}
You will, of course, also need to change the function prototype (just before your main) to match the new definition:
void bn_tree_free_node_space(bn_tree_node** nodes); // Must match definition!
Fruther, you will (clearly) need to change the calls to that function to pass the address of the node_processing_space pointer:
bn_tree_free_node_space(&node_processing_space); // Likewise for the other 3 calls!
Feel free to ask for further clarification and/or explanation.
1 EDIT: There are other ways (some may argue better ways) to implement your system, and also other 'minor' issues in your code. However, you did explicitly ask for "concise answers with minimal changes," so I have endeavoured to comply with that request!
I've adapted a very nice omp-parallelized code to perform numerical integration I found here.
However, some massif profiling revealed that there is some serious memory-leaking going on...
I guess this is related to how popping elements from the stack is handeled, where the top element on the stack is returned but not removed from the stack.
So I figured, I could easily add this missing feature as I've done this before in serial code.
But I'm obiously doing something wrong because I'm getting an "invalid pointer error" after a couple of "frees" ...
Since I'm completely new to OMP I figured, I could ask you guys for help.
I'm really sorry, that I wasn't able to cut done my "example" more.
But I think, that it's important to see how the author implemented the linked list and which datastructures.
I guess most of the code below may be skipped, it looks fine to me.
The problem arises when I try to "free" the data associated with the top element of the stack in the function "pop_stack" at the very end.
Popping elements in serial seems to work fine - inside the parallel section it doesn't.
Can you spot the mistake(s) ?
Note: This is incomplete code. It won't compile.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>
#include <math.h>
int num_threads;
#define INITIAL_STACK_SIZE 128
/* the stack structure */
struct stack_s{
int el_count; /* count of elements on stack */
int el_size; /* size of an element */
int mem_reserve; /* allocated memory for stack */
void* elements; /* pointer to begin of stack */
};
struct myparams { double c1; double c1;};
typedef struct _work_t{
double a;
double b;
double rec; /* max recursion depth */
struct myparams * p;
} work_t;
typedef struct stack_s* stack_t;
void create_stack(stack_t* stack, int element_size);
int empty_stack(stack_t stack);
void push_stack(stack_t stack, void* element);
void pop_stack(stack_t stack, void* element);
double do_something(
double (*f)(double,struct myparams*), /* function to be called */
double a,
double b,
int rec, /*max. recursion depth*/
struct myparams* p);
static double myfun(double x,struct myparams* p){ return exp(-x*x)/p->a+log(x*pow(p->b,2.0));}
int main(int argc,char** argv)
{
num_threads=omp_get_num_threads();
double a=somevalue;
double b=somevalue;
struct myparams pinit;
pinit.c1=someval;
pinit.c2=someval;
double answer=0;
#pragma omp parallel
{
answer = do_something(myfun, xmin, xmax, 100, &pinit);
} /* omp parallel */
return 0;
}
double do_something(
double (*f)(double,struct myparams*), /* function to be called */
double a,
double b,
int rec,
struct myparams* p)
{
stack_t stack;
work_t work;
int ready, idle, busy;
/* prepare stack */
work.a = a;
work.b = b;
work.rec=rec;
work.p=p;
create_stack(&stack, sizeof(work_t));
push_stack(stack, &work);
double result = 0.0;
busy = 0;
#pragma omp parallel default(none) \
shared(stack, result,f,busy) \
private(work, idle, ready)
{
ready = 0;
idle = 1;
while(!ready )
{
#pragma omp critical (stack)
{
if (!empty_stack(stack)){
/* we have new work */
pop_stack(stack, &work);
if (idle){
/* say others i'm busy */
busy += 1;
idle = 0;
}
}else{
/* no new work on stack */
if (!idle){
busy -= 1;
idle = 1;
}
/* nobody has anything to do; let us leave the loop */
if (busy == 0)
ready = 1;
}
} /* end critical(stack) */
if (idle)
continue;
/* do some calculations using values saved in work and as well as the function f
along with the function parameters saved in myparams
-> estimate an error & save it to 'delta' */
if(rec <= 0 || fabs(delta) <= global_tolerance)
{
//error acceptable
#pragma omp critical (result)
result += somevalue_computed_above;
}
else // error not acceptable
{
//push 2 new work-elements to stack
//prepare 1st new elem.
work.a = some_new_a;
work.b = some_new_b;
work.rec=rec-1;
#pragma omp critical (stack)
{
push_stack(stack, &work);
//prepare 2nd new element
work.a = some_new_a2;
work.b = some_new_b2;
work.rec=rec-1;
push_stack(stack, &work);
}
}
} /* while */
} /* end omp parallel */
return result;
}
/******************************************
* create new stack
******************************************/
void
create_stack(
stack_t* stack, /* stack to create */
int element_size) /* size of a stack element */
{
int initial_size = INITIAL_STACK_SIZE;
/* allocate memory for new stack struct */
(*stack) = (stack_t) malloc(sizeof(struct stack_s));
if (!(*stack)){
fprintf(stderr, "error: could not allocate memory for stack.. Abort.\n");
exit(1);
}
/* allocate memory for stack elements */
(*stack)->elements = (void*) malloc(element_size * initial_size);
(*stack)->mem_reserve = initial_size;
if (!(*stack)->elements){
fprintf(stderr, "error: could not allocate memory for stack.. Abort.\n");
exit(1);
}
(*stack)->el_size = element_size;
(*stack)->el_count = 0;
}
/*****************************************
* check if the stack is empty
*****************************************/
int
empty_stack
(stack_t stack)
{
return stack->el_count <= 0;
}
/*****************************************
* push a element on stack
*****************************************/
void
push_stack(
stack_t stack, /* target stack */
void* element) /* element to push */
{
int i, new_reserve;
int log2_count;
/* check if we need more memory for stack */
if (stack->el_count >= stack->mem_reserve){
/* calculate new size for the stack
it should be a power of two */
for (i = stack->el_count, log2_count = 0;
i > 0;
i>>1, log2_count++);
new_reserve = 1 << log2_count;
/* reallocate memory for phase thread tables
and nullify new values */
stack->elements = (void *) realloc(stack->elements,
stack->el_size * new_reserve);
if (!stack->elements){
fprintf(stderr, "error: can't reallocate stack.. Aborting\n");
exit(1);
}
stack->mem_reserve = new_reserve;
}
/* now push the element on top of the stack */
memcpy((char*)stack->elements + stack->el_count*stack->el_size,
element, stack->el_size);
stack->el_count++;
}
/*****************************************
* pop an element from stack
* THIS IS WHERE I SUSPECT A MISTAKE !
*****************************************/
void pop_stack(
stack_t stack, /* target stack */
void* element) /* where poped el. should be stored */
{
if (stack->el_count <= 0){
fprintf(stderr, "error: trying to pop from empty stack.\n");
exit(2);
}
stack->el_count--;
memcpy(element,
(char*)stack->elements + stack->el_count*stack->el_size,
stack->el_size);
// try to remove last element from stack
// in original code there was no cleanup
struct _work_t *tmp = (struct _work_t*) stack->elements+stack->el_count;
printf("ncount:%d, foo:%f\n",stack->el_count+1,tmp->a);
free(tmp); //Works as long as el_count == 1 but fails if it becomes 2
}
So it looks like pop_stack() is only called inside some stack related critical region, so we can stop worrying about data races.
You identify this part of the code:
/*****************************************
* pop an element from stack
* THIS IS WHERE I SUSPECT A MISTAKE !
*****************************************/
void pop_stack(
stack_t stack, /* target stack */
void* element) /* where poped el. should be stored */
{
if (stack->el_count <= 0){
fprintf(stderr, "error: trying to pop from empty stack.\n");
exit(2);
}
stack->el_count--;
memcpy(element,
(char*)stack->elements + stack->el_count*stack->el_size,
stack->el_size);
// try to remove last element from stack
// in original code there was no cleanup
struct _work_t *tmp = (struct _work_t*) stack->elements+stack->el_count;
printf("ncount:%d, foo:%f\n",stack->el_count+1,tmp->a);
free(tmp); //Works as long as el_count == 1 but fails if it becomes 2
}
as the possible seat of the problem. So the push_stack() clearly copies stack->el_size bytes of the element to the stack, and pop_stack() copies them back again. That all looks wonderful. The last part of pop_stack() is, however, a bit of a puzzle...
struct _work_t *tmp = (struct _work_t*) stack->elements+stack->el_count;
printf("ncount:%d, foo:%f\n",stack->el_count+1,tmp->a);
free(tmp); //Works as long as el_count == 1 but fails if it becomes 2
stack->elements is a void* pointer to the first byte of the first element, so adding stack->el_count to that does not give you the address of the element that has just been popped, except when stack->el_count == 0 !! So tmp is set to a nonsense value, and tmp->a is also, therefore, nonsense. As for the free(tmp)... only when el_count == 0 (now) will the free() not fail, but it will destroy the stack.
Looking at the way the stack works does not suggest to me that the pop_stack() needs to do any "cleanup". If you think it does, then you need to reconsider what that really needs to be. It's possible that you are using the stack as a stack of pointers to "stuff"... but in any case, there's a little more work to be done.
i need to create a thread pool it,it works but in function do_work that the function pthread_create calls i have problem in the free (memory leak) just when calling pthread_exit()
*in function create threadpool i just initilaize the struct and call
function do work *
void* do_work(void* p)
{
threadpool* pool = (threadpool*)p;
work_t* work;
while(1)
{
pthread_mutex_lock(&pool->qlock);
if(pool->shutdown == 1)
{
pthread_mutex_unlock(&pool->qlock);
//pthread_exit(EXIT_SUCCESS);// here is the free problem when deleting it all good
return NULL;
}
while(!pool->qsize)
{
if(pthread_cond_wait(&pool->q_not_empty,&pool->qlock))
perror("pthread_cond_wait\n");
if(pool->shutdown)
break;
}
//Check if the system is shutting down
if(pool->shutdown == 1)
{
pthread_mutex_unlock(&pool->qlock);
//pthread_exit(EXIT_SUCCESS);y
return NULL;
}
work = pool->qhead; //set the cur variable.
pool->qsize--; //decriment the size.
if(pool->qsize == 0) {
pool->qhead = NULL;
pool->qtail = NULL;
}
else {
pool->qhead = work->next;
}
if(pool->qsize == 0 && ! pool->shutdown) {
//the q is empty again, now signal that its empty.
pthread_cond_signal(&(pool->q_empty));
}
pthread_mutex_unlock(&(pool->qlock));
(work->routine) (work->arg); //actually do work.
free(work);
}
}
The pattern looks like a fairly standard thread pool:
typedef struct {
pthread_mutex_t qlock;
pthread_cond_t q_not_empty;
volatile work_t *qhead;
volatile work_t *qtail;
size_t qsize; /* Not needed */
volatile int shutdown;
} threadpool;
Properly indenting OP's code would make it more readable.
However, the implementation looks odd. I would expect
void *do_work(void *poolptr)
{
threadpool *const pool = poolptr;
work_t *work;
pthread_mutex_lock(&(pool->qlock));
while (!(pool->shutdown)) {
if (!(pool->qhead)) {
/* Queue empty */
pthread_cond_wait(&(pool->q_not_empty), &(pool->qlock));
continue;
}
work = pool->qhead;
pool->qhead = work->next;
if (!pool->qhead)
pool->qtail = NULL;
work->next = NULL;
pthread_unlock(&(pool->qlock));
work->process(work);
pthread_lock(&(pool->qlock));
}
pthread_mutex_unlock(&(pool->qlock));
return (void *)0;
}
and the code that appends a new work item to the queue to be
void append(threadpool *pool, work_t *work)
{
work->next = NULL;
pthread_mutex_lock(&(pool->qlock));
if (pool->qtail) {
pool->qtail->next = work;
pool->qtail = work;
} else {
pool->qhead = work;
pool->qtail = work;
}
pthread_cond_signal(&(pool->q_not_empty));
pthread_mutex_unlock(&(pool->qlock));
}
It is difficult to say where OP's implementation leaks memory. The most likely candidate is OP's arg member in each work_t, if it is dynamically allocated.
My implementation above passes the entire work_t to the routine function, which I renamed to process. It is responsible for freeing the work structure, too. The minimal definition for the work structure is
typedef struct work_t {
struct work_t *next;
void (*process)(struct work_t *);
/* Optional other fields */
} work_t;
Other possible causes for the memory leaks is if the qsize member is not properly updated everywhere. Because there is no use for it, really, I just omit it altogether.
The simpler the code, the easier it is to avoid bugs.
This is my first post, but I have been using this site for a while now, been very useful.
I am in the process of writing a memory-pool implementation but I have run into a strange problem. Right now I have 2 memory pools, there is an odd problem that whenever I initialize both of them the first array will have 1 more element than it is supposed to have. For each pool I add beyond the first it gains an additional element. It is not supposed to and I have no idea why.
In my code the first pool has 32 elements (0 - 31) which works fine, but when I initialize the second pool it shows as having 33 elements (0 - 32).
Here is my code :
#include <stdio.h>
typedef struct memoryBlock {
/* Pointer to array */
int *Address;
struct memoryBlock *Next;
}memoryBlock;
/* Small Pool */
#define BLOCKNUM_POOL_S 32 //number of blocks
#define BLOCKSIZE_POOL_S 8 //ints per block
static memoryBlock *Pool_Head_S;
static memoryBlock *Pool_Tail_S;
/* The memory that will be dynamically allocated will be stored in this array */
static int Pool_Block_S[BLOCKNUM_POOL_S-1][BLOCKSIZE_POOL_S+sizeof(memoryBlock)/sizeof(int)];
/* This is a free list containing only pointers to free blocks in this pool */
static int Pool_Free_S[BLOCKNUM_POOL_S-1][sizeof(memoryBlock)/sizeof(int)];
/* Medium Pool */
#define BLOCKNUM_POOL_M 16 //number of blocks
#define BLOCKSIZE_POOL_M 16 //words per block
static memoryBlock *Pool_Head_M;
static memoryBlock *Pool_Tail_M;
/* The memory that will be dynamically allocated will be stored in this array */
static int Pool_Block_M[BLOCKNUM_POOL_M-1][BLOCKSIZE_POOL_M+sizeof(memoryBlock)/sizeof(int)];
/* This is a free list containing only pointers to free blocks in this pool */
static int Pool_Free_M[BLOCKNUM_POOL_M-1][sizeof(memoryBlock)/sizeof(int)];
void printS();
void printM();
void initPool_S();
void initPool_M();
void main(){
initPool_S();
initPool_M();
printS();
printM();
}
void initPool_S(){
int i;
Pool_Tail_S = NULL;
Pool_Head_S = NULL;
for(i=0;i<BLOCKNUM_POOL_S;i++){
//for each block setup the memory block and pointers
if(Pool_Tail_S){
Pool_Tail_S->Next = (memoryBlock *)&Pool_Free_S[i][0];
Pool_Tail_S->Next->Address = &Pool_Block_S[i][0];
Pool_Tail_S = Pool_Tail_S->Next;
Pool_Tail_S->Next = NULL;
/* There is nothing in this list yet */
}else{
Pool_Head_S = (memoryBlock *)&Pool_Free_S[i][0];
Pool_Head_S->Address = (int *)&Pool_Block_S[i][0];
Pool_Head_S->Next = NULL;
Pool_Tail_S = Pool_Head_S;
}
}
}
void initPool_M(){
int i;
Pool_Tail_M = NULL;
Pool_Head_M = NULL;
for(i=0;i<BLOCKNUM_POOL_M;i++){
//for each block setup the memory block and pointers
if(Pool_Tail_M){
Pool_Tail_M->Next = (memoryBlock *)&Pool_Free_M[i][0];
Pool_Tail_M->Next->Address = (int *)&Pool_Block_M[i][0];
Pool_Tail_M = Pool_Tail_M->Next;
Pool_Tail_M->Next = NULL;
/* There is nothing in this list yet */
}else{
Pool_Head_M = (memoryBlock *)&Pool_Free_M[i][0];
Pool_Head_M->Address = (int *)&Pool_Block_M[i][0];
Pool_Head_M->Next = NULL;
Pool_Tail_M = Pool_Head_M;
}
}
}
void printM(){
memoryBlock *tmpPtr2;
tmpPtr2 = Pool_Head_M;
int j=0;
while(tmpPtr2){
printf(">-------------------------------------------------<\n");
printf("%d\n",j);
printf("Pool_Med_Free: %d\n",tmpPtr2);
printf("Pool_Med_Free->Address: %d\n",tmpPtr2->Address);
printf("Pool_Med_Free->Next: %d\n",tmpPtr2->Next);
tmpPtr2 = tmpPtr2->Next;
j++;
}
}
void printS(){
memoryBlock *tmpPtr1;
tmpPtr1 = Pool_Head_S;
int j=0;
while(tmpPtr1){
printf(">-------------------------------------------------<\n");
printf("%d\n",j);
printf("Pool_Small_Free: %d\n",tmpPtr1);
printf("Pool_Small_Free->Address: %d\n",tmpPtr1->Address);
printf("Pool_Small_Free->Next: %d\n",tmpPtr1->Next);
tmpPtr1 = tmpPtr1->Next;
j++;
}
}
Also the compiler I am using is minGW.
I am still somewhat new to C so this is probably a stupid mistake, but I cannot seem to solve it. Any Help would be appreciated, Thanks!
Pool_Block_S[BLOCKNUM_POOL_S-1] has only 31 elements. n in array[n] is number of elements not index of last element. This is the source of your problem.
What is the meaning of sizeof(memoryBlock)/sizeof(int)? It doesn't look correctly.
this might be a bit long so my apologies.
consider the following code (i've left some irrelevant parts from it). this code receives a pointer to a struct (BoardP theBoard), x & y coords and a value.
the goal is to place the value in a 2D array that is found in the struct.
if the coords are out of bounds, i have to increase the size of the table, copy old data to new data and place the value in its place.
well this code works the first call but in the second call it crashes and writes:
*** glibc detected *** ./b: double free or corruption (top): 0x092ae138 ***
i couldn't find an answer to it and i hope you will help.
These are the calls from main()
BoardP p = CreateNewBoard(10,10);
PutBoardSquare(p,10,5,'X');
PutBoardSquare(p,5,10,'O');
Boolean PutBoardSquare(BoardP theBoard, int X, int Y, char val) {
if (inBounds(X,Y,theBoard->_rows,theBoard->_cols)) {
theBoard->_board[X * theBoard->_cols + Y] = val;
return TRUE;
}
else {
int newRows = (X>=theBoard->_rows) ? (2*X) : theBoard->_rows;
int newCols = (Y>=theBoard->_cols) ? (2*Y) : theBoard->_cols;
BoardP newBoard = CreateNewBoard(newCols,newRows); //this creates a new Board with the new dimensions
if (newBoard == NULL) {
//ReportError(MEM_OUT);
return FALSE;
}
else {
copyData(theBoard,newBoard);
freeBoardArray(&theBoard->_board[0]); //free old array
theBoard->_board = newBoard->_board; //old array point to new array
FreeBoard(newBoard); //free the temp copy THIS CAUSES THE PROBLEM
PutBoardSquare(theBoard,X,Y,val);//recursion, will be in bounds now
return TRUE;
}
}
}
These are the Free functions:
void FreeBoard(BoardP board) {
if (board != NULL) {
printf("FREE 1\n");
//free the board array:
if (board->_board != NULL) {
printf("FREE 2\n");
freeBoardArray(&board->_board[0]);
printf("FREE 3\n");
}
free(board);
}
}
static void freeBoardArray(char * arrP) {
free(arrP); //**PROGRAM CRASH HERE**
}
This is how i create a new board:
BoardP CreateNewBoard(int width, int high) {
BoardP board = (BoardP) malloc(sizeof(Board));
if (board != NULL) {
board->_board = allocateBoardArray(high,width);
if ( board->_board == NULL) {
FreeBoard(board);
//TODO make file ReportError(MEM_OUT);
return NULL;
}
initializeBoard(board,high,width,X_SIGN,SPACE);
return board;
}
else {
FreeBoard(board);
//TODO make file ReportError(MEM_OUT);
return NULL;
}
}
static char* allocateBoardArray(int row, int col) {
char* newBoard = (char*) malloc(row * col * sizeof(char));
if (newBoard == NULL) {
return NULL;
}
return newBoard;
}
this is BoardP:
typedef struct Board* BoardP;
You have to free memory which you have allocated and no longer want to hold a reference too.
from your code i can see the following line.
theBoard->_board = newBoard->_board;
Now you maintain reference to a allocated pointer and then free that same pointer itself.
Example code:
char *foo()
{
char *ref1;
char *ref2;
ref1 = malloc(256);
ref2=ref1;// Holding reference to a pointer in another pointer
strcpy(ref1,"stackoverflow");
printf("%s %s",ref1,ref2); // This prints stackoverflow twice
free(ref1); // This is valid but you can access ref2 or ref1 after this point
return ref2; /// This will cause problems
}
Try this:
copyData(theBoard, newBoard);
/* swap the _board pointers */
char * b = theBoard->_board;
theBoard->_board = newBoard->_board;
newBoard->_board = b;
FreeBoard(newBoard); /* cleanup the temp struct and the old array */
This errors says that you are trying to free the memory which is already freed by you. What i am suspecting here is this block of code
if (board != NULL) {
printf("FREE 1\n");
//free the board array:
if (board->_board != NULL) {
printf("FREE 2\n");
freeBoardArray(&board->_board[0]);
printf("FREE 3\n");
}
free(board);
once you are freeing the part of structure freeBoardArray(&board->_board[0]); and then you are freeing the whole structure free(board);, and it looks to me causing the problem.Why you passing the address of the _board pointer?I wrote the code on the same line of code,which causing the problem.
struct a{
int * next;
};
int main(){
struct a *aptr = (struct a *)malloc(sizeof(struct a));
aptr->next=(int *)malloc(5*sizeof(int));
free(&aptr->next);
free(aptr);
return 0;
}
this code will cause the same issue as you shown. Now again try this code after removing '&' from free(&aptr->next);statement.It will work fine.
So i think you got a clue where you have to modify.
Running this code under valgrind will tell you exactly on which line you a.) first freed the memory and b.) when you tried to free it again.
It will also tell you if you try and access any addresses which are inside a block that you have freed.