Freeing a dynamically allocated 2D structure
I've dynamically allocated a structure, conceptually very similar to a matrix, to hold a set of strings. I've encountered a problem while trying to free the memory. My code looks like this:
# include <stdio.h>
# include <string.h>
# include <malloc.h>
# define SIZE 2
typedef struct fork{
char** dataPointersArray;
char* dataArray;
}fork;
int main(int argc, char* argv[]){
fork forkDS;
int i;
char* dataArrayPtr;
unsigned char data[255] = "some data"; /* this is actually a function's output */
int PtrIndex;
/* allocate memory for the arrays */
forkDS.dataPointersArray = (char**) calloc(SIZE ,sizeof(char*));
if(forkDS.dataPointersArray == NULL){
printf("couldn't allocate memory \n");
}
forkDS.dataArray = (char*) calloc(SIZE, 255);
if( forkDS.dataArray == NULL){
free(forkDS.dataPointersArray);
printf("couldn't allocate memory \n");
}
dataArrayPtr = forkDS.dataArray;
for(i = 0; i < SIZE; i++){
/* update the dataPointers Array */
forkDS.dataPointersArray[i] = dataArrayPtr;
/* copy data into data array */
memcpy(dataArrayPtr,data,20);
dataArrayPtr[255] = '\0';
/* update the pointer of the data array */
dataArrayPtr = dataArrayPtr + 256;
}
for (PtrIndex = 0; PtrIndex < 2; PtrIndex++) {
if (*(forkDS.dataPointersArray + PtrIndex) != NULL) {
*(forkDS.dataPointersArray + PtrIndex) = NULL;
}
}
/* DEBUG comment - this 2 lines works */
free(forkDS.dataArray);
forkDS.dataArray = NULL;
/* DEBUG comment - the next line fails */
free(forkDS.dataPointersArray);
forkDS.dataPointersArray = NULL;
return 0;
}
So the structure actually contains 2 arrays, one of pointers to strings, and the other one contains the strings aligned one after the other, separated by a terminating \0.
The code works fine, and the for loop in the end works as well. The first call to free also works. The problem is that the last call to free fails. Although trying to search all possible data on the issue, all the examples I've found regarded the case where the second array, which holds the strings, is allocated step by step in a for loop, and freed afterwards in a for loop as well.
I wanted to avoid using dynamic allocation in a loop, and therefore my code looks different.
Does anyone know what the problem开发者_运维知识库 is?
======================================================================================
Thanks a lot to all of you who answered me. Eventually, the bug was solved. The problem was that the dataPointersArray was filled with more than SIZE elements in some other piece of code, which seemed innocent at first, and actually caused the free call to fail.
Thanks again for the comments! Shachar
You are allocating SIZE*255 bytes, but using SIZE * 256 bytes:
forkDS.dataArray = (char*) calloc(SIZE, 255);
dataArrayPtr = forkDS.dataArray;
//SIZE TIMES loop:
dataArrayPtr = dataArrayPtr + 256;
So when you are NULLing the pointers, you probably overwrite control data placed past the end of the array by malloc that free is looking for.
You allocated the space for an array consisting of SIZE lines with 255 characters each. The highest index on each line therefore is 254 = 255 - 1. As you write the \0 character, you write it at the beginning of the next line. After the last iteration, you would be off by SIZE bytes.
Just another detail: If any of the memory allocations failed, the program would only print its error messages, but it won't stop causing a SEGFAULT later.
精彩评论