I'm take some errors trying free memory. A post all my code below.
I'm using ubuntu and I compile my code with gcc. But when I try execute my code I take an error while trying free memory.
I put comments on my code to explain my doubt. I'm working with stack structre.
How Do I free memory without take error to turn free memory for char?
If I whoud not free the memory allocated for the data (a char), and only to free the memory for the element (which contains the char data), which happens with memory allocated to the data? is it free?
ERROR
{
*** glibc detected *** ./pilha: free(): invalid next size (fast): 0x08b86018 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x74f82)[0xb7637f82]
./pilha[0x80485ba]
./pilha[0x804864c]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb75dc4d3]
./pilha[0x8048411]
======= Memory map: ========
}
CODE
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct Stack_element{
char *data;
struct Stack_element *next;
}Element;
typedef struct Position{
Element *top;
int size;
}stack;
void start(stack *aux){
aux->top = NULL;
aux->size = 0;
}
int push(stack *aux, char value){
Element *new_element;
if ((new_element = (Element*) malloc(sizeof(Element))) == NULL)
return -1; //an error occur
if ((new_element->data = (char*) malloc(sizeof(char))) == NULL)
return -1; //an error occur
strcpy(new_element->data, &value);
new_element->next = aux->top;
aux->top = new_element;
aux->size++;
}
int empty(stack *aux){
if ((aux->size) == 0){
return -1;
}
return 0;
}
char pop(stack *aux){
Element *element;
char value='0';
if (empty(aux)){
return '1';
}
element = aux->top;
aux->top = aux->top->next;
/*
To observe the line below. When a element exist in the stack and
I try remove this element, first I free the data in that node (element)
so I turn free memory allocated for the element.
If I didn't free data memory allocated before (in push fuction), I
don't get any error. But the memory allocated for the data, what happens?
Does is it continues allocated?
*/
value = *(element->data);
free(element->data);//THE ERROR OCCURS HERE, IN THIS LINE
free(element);//Just after free the data element memory, I also free the element's memory
aux->size--;
return value;
}
int main(){
stack p;
char value;
start(&p);
//no error occurs. there isn't any element at this moment.
printf("%c\n",pop(&p));
//valor = 't';
if (push(&p, 't')){
printf("Add a char\n");
}
pop(&p);//the error occurrs now, after insert an new element in the stack
printf("The End.");
}
In your code,
strcpy(new_element->data, &value);
is not correct. You have allocated memory for only one char which is not having space for null terminator. Instead you should use
*(new_element->data) = value;
Otherwise, with the improper usage of strcpy(), you'e messing up the allocated memory by making memory overrung which causes undefined behaviour.
At least this statement in function push is invalid
strcpy(new_element->data, &value);
You should write
if ( ( new_element->data = (char*) malloc( 2 * sizeof(char))) == NULL)
{
free( new_element );
return -1; //an error occur
}
new_element->data[0] = value;
new_element->data[1] = '\0';
Or
if ( ( new_element->data = (char*) malloc( sizeof(char))) == NULL)
{
free( new_element );
return -1; //an error occur
}
*new_element->data = value;
Function empty looks strange. Usually -1 is returned from a function when some error occurred. As for the function empty then neither error can occur. So it is better when the function returns 1 if the stack is empty. I would write it like
int empty( stack *aux )
{
return aux->size == 0;
}
Also it is not clear why function pop returns character '1' when the stack is empty. It would be better if it returns simply '\0'. So instead of
char pop(stack *aux){
Element *element;
char value='0';
if (empty(aux)){
return '1';
}
//,,
I would write
char pop(stack *aux){
if ( empty( aux ) ) return '\0';
Element *element;
//,,
Related
I am trying to understand why valgrind is screaming at me (pretty new to C programming and valgrind).
I implemented a generic linked list (found in github - thanks to fabianosalles) that holds struct that looks like this:
typedef struct symbol_entity
{
/* Symbol name */
char *name;
/* Symbol address */
unsigned int address;
/* Indicates if symbol is extern */
bool is_extern;
/* Indicates if symbol is entry */
bool is_entry;
/* Indicates if symbol is instruction */
bool is_instruction;
/* Indicates if symbol is opcode */
bool is_opcode;
} symbol_entity;
Furthermore, I implemented a method that insert data to the linked list called add_symbol_to_list_with_result.
It returns true and set result_symbol to the one who was added to list in case added successfully. Otherwise if symbol already exists it returns false and should initialize result_symbol to null. (maybe there is a better choice, you are more than welcome to suggest!)
bool add_symbol_to_list_with_result(linked_list **symbols, char *name, bool is_extern, bool is_entry, bool is_instruction, bool is_opcode, unsigned int address, symbol_entity **result_symbol)
{
*result_symbol = (symbol_entity *)verified_malloc(sizeof(symbol_entity));
(*result_symbol)->name = verified_malloc(sizeof(char) * strlen(name));
strncpy((*result_symbol)->name, name, strlen(name));
(*result_symbol)->is_extern = is_extern;
(*result_symbol)->is_entry = is_entry;
(*result_symbol)->is_instruction = is_instruction;
(*result_symbol)->address = address;
(*result_symbol)->is_opcode = is_opcode;
if (!list_contains(*symbols, *result_symbol))
{
list_add(*symbols, *result_symbol);
return TRUE;
}
free(*result_symbol);
result_symbol = NULL;
return FALSE;
}
list_add looks like:
void list_add(linked_list *list, void *data)
{
node_item *newNode;
if (list != NULL && data != NULL)
{
newNode = verified_malloc(sizeof(node_item));
newNode->data = verified_malloc(list->data_size);
memcpy(newNode->data, data, list->data_size);
if (list->head == NULL)
{
list->head = newNode;
list->tail = newNode;
}
else
{
list->tail->next = newNode;
list->tail = newNode;
}
list->count++;
}
}
and of course verified malloc looks like:
void *verified_malloc(long size)
{
void *ptr;
ptr = malloc(size);
if (ptr == NULL)
{
printf("Fatal error! Memory allocation failed!");
exit(1);
}
return ptr;
}
add_symbol_to_list_with_result method get called multiple times, and I can see in valgrind output stuff like that:
==9179== Uninitialised value was created by a heap allocation
==9179== at 0x402D17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==9179== by 0x804C074: verified_malloc (in /home/user/.....)
==9179== by 0x804A0F5: list_add (in /home/user/.....)
==9179== by 0x804B4E6: add_symbol_to_list_with_result (in /home/user/.....)
=
.
.
.
==9179== Address 0x4263d94 is 0 bytes after a block of size 4 alloc'd
==9179== at 0x402D17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==9179== by 0x804C074: verified_malloc (in /home/user/.....)
==9179== by 0x804B454: add_symbol_to_list_with_result (in /home/user/.....)
Any help with this type of output?
EDIT:
symbols is declared in a different C file:
linked_list *symbols;
linked_list initialized with this method:
linked_list *list_create(int dataSize, callback_free free_callback, callback_compare compare_callback)
{
linked_list *list;
if (dataSize > 0)
{
/* Initialize parameters in linked list */
list = (linked_list *)verified_malloc(sizeof(linked_list));
list->count = 0;
list->data_size = dataSize;
list->head = NULL;
list->tail = NULL;
list->callback_free = free_callback;
list->callback_compare = compare_callback;
}
return list;
}
and is passes to multiple methods using &symbols
Please try
(*result_symbol)->name = verified_malloc(sizeof(char) * (strlen(name)+1));
to account for the required "\0" at end of string.
And after line
strncpy((*result_symbol)->name, name, strlen(name));
include the line
(*result_symbol)->name[strlen(name)]='\0'
just to be sure.
Furthermore, I would guess an allocation problem for **symbol which goes into bool add_symbol_to_list_with_result - please show the allocation for **symbol.
Question
Is list->data_size equal to sizeof(symbol_entity)?
memcpy(newNode->data, data, list->data_size);
Please try
memcpy(newNode->data, data, sizeof(symbol_entity));
Memory handling
Please note that your memory handling of *result_symbol is not accurate: In case of return TRUE, you keep *result_symbol completely, although only char array of name pointer would be required (*result_symbol was copied.)
In case of return FALSE, you free *result_symbol, but not the name pointer.
In both cases some memory is lost.
Missing code
Yes, the additional code which you provided is useful. However, as larger parts, like the other typedef structdefinitions and any memory handling above the provided subroutines is missing, ... I can not see anything more. In the beginning, you refer to github. Do you have link to more (the full) code?
I just started learning C recently, and am having issues figuring out memory allocation. I have spent about the last 2~3 days in my extra time trying to figure this out, but have not found a solution yet. So first, I have two structs:
struct _list {
// arr is an array of string arrays
char **arr;
// recs tracks how many records are in the list
size_t recs;
// arrSizes records the size of each string array in arr
size_t *arrSizes;
};
typedef struct _list list_t;
and
struct _string {
char *string;
// size is used to store strlen
size_t size;
};
typedef struct _string string_t;
I initialize the above structs respectively in the following ways.
list_t:
list_t *NewList() {
list_t *List = NULL;
List = malloc(sizeof(*List));
if (List == NULL) {
fprintf(stderr, "Failed to allocate memory to list structure.\n");
return NULL;
}
List->arr = malloc(sizeof(List->arr));
if (List->arr == NULL) {
free(List);
fprintf(stderr, "Failed to allocate memory to list array.\n");
return NULL;
}
List->arrSizes = malloc(sizeof(List->arrSizes));
if (List->arr == NULL) {
free(List);
fprintf(stderr, "Failed to allocate memory to size array.\n");
return NULL;
}
List->recs = 0;
return List;
}
string_t:
// a string array read in by the program is passed with "char* record"
string_t *NewString(char *record)
{
string_t *String = NULL;
String = malloc(sizeof * String);
if (String == NULL) {
fprintf(stderr, "Failed to allocate memory to string structure.\n");
return NULL;
}
String->size = strlen(record) + 1;
String->string = malloc(String->size);
if (String->string == NULL) {
free(String);
fprintf(stderr, "Failed to allocate memory to string array.\n");
return NULL;
}
strcpy(String->string, record);
return String;
}
I read lines from a file and load them into a "matching results" buffer using something like the following code. Please ignore exits and the fact that I don't have null handling after struct initialization is complete; I will add something more useful later. Also, sorry about the length. I edited quite a bit to produce the smallest example I could think of that reproduces the issue.
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
// Check if File exists
void FileExists(FILE *FilePath) {
if (FilePath == NULL) {
fprintf(stderr, "Error: File not found.\n");
exit(1);
}
}
// Delete a string_t struct
int delString(string_t *Structure)
{
if (Structure != NULL) {
free(Structure->string);
free(Structure);
return 0;
}
return 1;
}
// Allocate memory for additional elements added to members of list_t struct
void AllocList(list_t *List, size_t StrLen)
{
char **ArrStrArr_tmp;
size_t *SizeArr_tmp;
char *StrArr_tmp;
ArrStrArr_tmp = realloc(*List->arr, sizeof(**ArrStrArr_tmp) * List->recs);
SizeArr_tmp = realloc(List->arrSizes, sizeof(*SizeArr_tmp) * List->recs);
StrArr_tmp = malloc(sizeof(*StrArr_tmp) * StrLen);
if ((ArrStrArr_tmp == NULL) || (SizeArr_tmp == NULL)
|| (StrArr_tmp == NULL)) {
fprintf(stderr, "Failed to allocate memory.\n");
exit(1);
}
else {
List->arr = ArrStrArr_tmp;
List->arrSizes = SizeArr_tmp;
(List->arr)[List->recs-1]= StrArr_tmp;
}
}
// Add a record to a buffer
int AddRecord(list_t *List, char *AppendRecord)
{
string_t *line = NewString(AppendRecord);
List->recs++;
AllocList(List, line->size);
(List->arr)[List->recs - 1] = line->string;
(List->arrSizes)[List->recs - 1] = line->size;
delString(line);
return 0;
}
// Sends entire string array to lowercase
void tolowerString(char *UpperString, size_t StrLen)
{
int i;
for (i = 0; i < (int)StrLen; i++) {
UpperString[i] = (char)tolower(UpperString[i]);
}
}
// Attempt to match string in lines from a file; lines with matches are read into a buffer
int main()
{
char line[80];
int PrintedLines = 0;
list_t *ResultList = NewList();
char *MyString = "theme";
char *Filename = "List.txt";
FILE *in = fopen(Filename, "r");
// Check if file exists
FileExists(in);
while (fscanf(in, "%79[^\n]\n", line) == 1)
{
char LookString[80];
strcpy(LookString, line);
LookString[strlen(LookString) - 1] = '\0';
// send lookstring to lowercase
tolowerString(LookString, strlen(LookString));
// add line to buffer ResultList if it contains MyString
if (strstr(LookString, MyString)) {
AddRecord(ResultList, line);
PrintedLines++;
}
}
// If PrintedLines is at zero after the while statement terminates, return in abnormal state
if (PrintedLines == 0) {
fprintf(stderr, "No matches found. Please check your input if you are sure there is a match.\n");
return 1;
}
fclose(in);
return 0;
}
When trying to read the 5th matching record into my buffer, my program crashes at this line in the AllocList function:
ArrStrArr_tmp = realloc(*List->arr, sizeof(**ArrStrArr_tmp) * List->recs);
I get the following message on the version I have posted above:
realloc(): invalid old size
aborted (core dumped)
My guess is that I'm running into an error after some default amount of memory from my initial malloc is used, but I have no clue what is actually causing this. In my actual code I'm printing all sorts of things (pointer sizes, etc.), but I still can't spot anything. What's strange is, before writing this post, I was actually seeing the error:
realloc(): invalid next size
aborted (core dumped)
But I can't reproduce it now for some reason...
I have also read that I should reallocating memory for my list_t struct whenever I add an element to one of it's members, but reallocating it actually doesn't change where or how this program crashes. In any case, I'm not sure how I should be reallocating memory for my struct. To clarify, my questions are:
What is causing this memory issue?
Should I be reallocating memory for my list struct, and how much should I be reallocating given that I'm adding an extra element to the arr and arrSizes members?
As the crash suggests, the line
ArrStrArr_tmp = realloc(*List->arr, sizeof(**ArrStrArr_tmp) * List->recs);
is wrong.
This have it read an uninitialized buffer allocated via malloc(), whose value is indeterminate.
The intension of this line is to re-allocate the array pointed at by List->arr, which is an array of char*.
Therefore, the line should be
ArrStrArr_tmp = realloc(List->arr, sizeof(*ArrStrArr_tmp) * List->recs);
just like the following line, which is re-allocating an array of size_t.
SizeArr_tmp = realloc(List->arrSizes, sizeof(*SizeArr_tmp) * List->recs);
Also I found 2 more points for improvement:
Firstly, the usage of some malloc() in the function NewList are not good.
The function is creating zero-element array, so you won't need space for List->arr and List->arrSizes.
Also note that realloc() accepts NULL as the buffer to re-allocate.
list_t *NewList() {
list_t *List = NULL;
List = malloc(sizeof(*List));
if (List == NULL) {
fprintf(stderr, "Failed to allocate memory to list structure.\n");
return NULL;
}
List->arr = NULL;
List->arrSizes = NULL;
List->recs = 0;
return List;
}
Secondly, you are copying pointer instead of string in AddRecord,
so you have problems of memory leak and potential use-after-free.
It seems the string should be copied:
(List->arr)[List->recs - 1] = line->string;
should be
strcpy((List->arr)[List->recs - 1], line->string);
Apologies for the really bad question - I wasn't really sure how to word it.
I'm executing a piece of code where I'm trying to use a dynamic array. It is segfault-ing at this line:
void myFunction(....) {
// other code up here
Stack *s = stack_new(); //segfault here
}
The relevant header file for my struct is:
typedef struct {
void **A;
int size;
int top; // the index of the current top of the stack
} Stack;
and the function stack_new() is:
Stack
*stack_new() {
Stack *s;
s->size = 1;
s->top = -1;
s->A = (void **)malloc(s->size);
return s;
}
I think I've included everything that is relevant, but please let me know if you need more code.
I think that the problem is with the way I'm using malloc, but have had a search online and have tried a few different options and am still getting the segfault. Is anyone able to offer some insight?
Thank you heaps
This is your problem:
Stack *s;
s->size = 1;
you're not actually allocating a Stack. s is uninitialized and points to an arbitrary location in the memory. s->size will obviously fail then.
Try:
Stack *s = malloc(sizeof(*s));
if (s == NULL)
{
fprintf(stderr, "Memory allocation error\n");
exit(1);
}
s->size = 1;
Note: you should also check if s->A is NULL. If so, return an error code (such as NULL) and before that remember to free the Stack you allocated, or alternatively print an error message and exit the program. If you exit the program, the operating system will reclaim all memory used so no need to do it explicitly then.
Another note: when doing
s->size = 1;
s->top = -1;
s->A = (void **)malloc(s->size);
...you allocate 1 byte of memory even though you should be allocating sizeof(void*) bytes of memory. Try doing
s->A = (void **)malloc(s->size*sizeof(void*));
instead.
Here's your first problem:
Stack *s;
s->size = 1;
What do you actually expect the value of s is at this point? It could be literally anything. You can't set a field of a struct if the struct itself isn't already allocated.
Try:
Stack *s = malloc(sizeof(*s));
if(!s){
//... error checking / exiting ..
}
and then everything else you were doing.
You are accessing a not initialized pointer!
Stack
*stack_new() {
Stack *s = std::nullptr; // initialize this pointer with nullptr
// and then you will see later (one line
// beyond) that you will try to access a
// null pointer
s->size = 1; // the problem occurs here!!
// you are accessing a pointer, for which has never
// been allocated any memory
s->top = -1;
s->A = (void **)malloc(s->size);
return s;
}
You will have to use "malloc" to allocate some memory for this pointer.
sth. like this is missing between those two lines, I commented:
Stack
*stack_new() {
Stack *s = (Stack*)malloc(sizeof(Stack));
s->size = 1;
s->top = -1;
s->A = (void **)malloc(s->size);
return s;
}
I'm trying to allocate some memory with realloc(). This works so far. But if I want to assign the allocated memory to a pointer in a struct variable, I get a segmentation fault:
// in header
typedef struct {
int a;
char test[20];
} MyContent;
typedef struct {
MyContent* values;
// simmilar to: MyContent values[]
// ... some other stuff
} MyData;
// in source
void myFunction(MyData* dataPtr) {
dataPtr->values = NULL;
MyData* tempPtr = NULL;
for (int i = 1; i < 10; i++) {
tempPtr = (MyContent*) realloc(dataPtr->values, i * sizeof(MyContent));
if (tempPtr == NULL) {
free(dataPtr->values);
break;
}
dataPtr->values = tempPtr; // Here I get the segmentation fault
dataPtr->values[(i-1)].a = 42;
// ...
}
}
I can't figure out what's going wrong here. Any suggestions? Thanks for your help.
Seems like you edited your code. The edited code works just fine.
#include<stdio.h>
#include<malloc.h>
#include<string.h>
// in header
typedef struct {
int a;
char test[20];
} MyContent;
typedef struct {
MyContent* values;
// simmilar to: MyContent values[]
// ... some other stuff
} MyData;
// in source
void myFunction(MyData* dataPtr) {
dataPtr->values = NULL;
MyData* tempPtr;
for (int i = 1; i < 10; i++) {
tempPtr = (MyData*) realloc(dataPtr->values, i * sizeof(MyContent));
if (tempPtr == NULL) {
if(dataPtr->values)
free(dataPtr->values);
printf("realloc() failed\n");
return ;
}
dataPtr->values = (MyContent*)tempPtr; // Here I get the segmentation fault
dataPtr->values[(i-1)].a = 42+i;
strcpy(dataPtr->values[(i-1)].test,"name");
}
}
void PrintData(MyData* dataPtr) {
for (int i = 1; i < 10; i++)
printf("We have %s at %d\n",dataPtr->values[(i-1)].test,dataPtr->values[(i-1)].a);
}
main() {
MyData Sample;
myFunction(&Sample);
PrintData(&Sample);
}
At first glance, I don't see a problem that could cause a crash there - that ones-based addressing is a bit odd, but not incorrect. There could be a problem in the code that you're not showing that results in heap or stack corruption that the realloc call makes worse. Or if you are compiling with optimizations, your debugger might be confused about where the crash is actually occurring. You're also confusing MyData and MyContent, but I'll assume that's just because you made an error while redacting the code.
Note also that if realloc fails, you will crash on the line after the one you indicated, as you'll be writing to a null pointer. You need to abort if tempPtr is NULL, not just free the old pointer. Again, though, this causes a fault on a different line than you indicated.
I'd recommend running your program under valgrind to see where it reports errors - the first such error to occur is likely to be the culprit.
Your condition is wrong for checking the newly allocated memory. It should be:
if (tempPtr == NULL) {
// handle error condition or continue with original 'dataPtr->values'
}
else {
dataPtr->values = tempPtr;
}
Remember that realloc() doesn't necessarily transfer one block to the another block. Sometimes it may allocate the memory in the same pointer region.
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.