My program crashes whenever i try to delocate the old memory - c

so basically there is a function that allocates a new pointer memory and when i try to delocate the old one the program basically crashes my code
char** AddingToTheBook(char** original, int* size, char *number)
{
char** newArray = (char**)malloc(sizeof(char*)*(*size));
//allocating and copying the values
for (int i = 0; i < *size; i++)
{
*(newArray + i) = (char*)malloc(sizeof(char)*(strlen(*(original + i))));
strcpy(*(newArray + i), *(original + i));
}
//allocating a new memory to the new number
*(newArray + (*size)) = (char*)malloc(sizeof(char)*strlen(number));
strcpy(*(newArray + (*size)), number);
(*size)++;
//delocating the allocated memories
for (int i = 0; i < size; i++)
free(original[i]);
free(original);
return newArray;
}

You are freeing too much of your original memory.
Look at the for loop when you're freeing the memory:
(*size)++;
//delocating the allocated memories
for (int i = 0; i < size; i++)
free(original[i]);
Since size is a int * you will end up with a very big number of iterations which will free to free much more memory than you allocated. To fix this do the following:
(*size)++;
//delocating the allocated memories
for (int i = 0; i < *size; i++)
free(original[i]);
Now you're still freeing one element too much since you've incremented *size when adding a new element. The final version to free the original memory is
(*size)++;
//delocating the allocated memories
for (int i = 0; i < *size - 1; i++)
free(original[i]);

strlen only returns the number of chars. Make room for the ending zero
*(newArray + i) = (char*)malloc(sizeof(char)*(strlen(*(original + i))) +1);
Better to strncpy instead of strcpy
How can you go *size ahead in newArray:
*(newArray + (*size)) = (char*)malloc(sizeof(char)*strlen(number));
You can only go *size -1 ahead, since it starts from zero.
In the for loop, it seems you forgot to add the asterisk *
for (int i = 0; i < size; i++)

You can use realloc instead
char** AddingToTheBook(char** original, size_t oldsize, char *number)
{
char** tmp = realloc(**original, (oldsize + 1) * sizeof(char *));
if(tmp)
{
tmp[oldsize] = malloc(strlen(number) + 1'
if(tmp[oldsize])
{
strcpy(tmp[oldsize], number);
}
else
{
/* do something for example realloc back to the old size */
tmp = NULL;
}
}
return tmp;
}
example correct usage
char **tmp = AddingToTheBook(book, size, "Test String")
if(tmp)
{
book = tmp;
size++;
}
else
{
/* do something adding to book failed */
}

Related

How to properly free memory inside a function that increases the rows of a 2D char array

I have a function that increases the rows of a 2D char array, which does contain elements in it. Am I supposed to free the memory after using calloc? How do I do that inside the function? I am getting memory leaks and I think it may be due to me not using free.
char **decode_structure;
void make_row_decode_structure_bigger(int rows){
//printf("inside the making the rows bigger \n");
int max_rows = rows+1;
char **store = realloc( decode_structure, sizeof *decode_structure * (rows + 1) );
//printf("after a store has been assigned\n");
if (store){
decode_structure = store;
for(size_t i = 0; i < 1; i++ ){
decode_structure[rows + i] = calloc(15, sizeof(char));
decode_structure[rows + i][0] = '\0';
}
}
//printf("end of making the rows increase\n");
return;
}
//in main()
decode_structure = (char**)calloc( 2, sizeof(char*) );
for(size_t i = 0; i < 2; i++){
decode_structure[i] = calloc(15, sizeof(char));
decode_structure[i][0] = '\0';
}
here is the error message that showed up:
* Error in `./prog': free(): corrupted unsorted chunks: 0x0000000001937010 *

Allocating memory for pointer struct which has pointer members

I am trying to read and print using struct pointer which has pointer members. So I am trying to read and print array of double struct pointers.
I tried the folowing but it is giving me error saying "Access violation writing location (somewhere in memory)"
How can I allocate memory dynamically for this?
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include<string.h>
#include <stdlib.h>
typedef struct template{
char *name;
int *birthdate;
int *phoneNum;
} detailsOf;
void inputValue(detailsOf **person, int maxSize);
int main() {
detailsOf **person;
int maxSize = 0, menu = 0;
printf("Max:");
scanf("%d", &maxSize);
person = (detailsOf **)malloc(maxSize * sizeof(detailsOf **));
if (person == NULL) {
printf("Failed to allocate");
exit(0);
}
for (int i = 0; i < maxSize; i++) {
person[i]->name = (char *)calloc(21, sizeof(char ));
person[i]->birthdate = (int *)calloc(8, sizeof(int ));
person[i]->phoneNum = (int *)calloc(16, sizeof(int ));
}
inputValue(person, maxSize);
for (int i = 0; i < maxSize; i++) {
free(person[i]);
for (int j = 0; j < 21; j++) {
free(person[i]->name[j]);
}
for (int j = 0; j < 15; j++) {
free(person[i]->phoneNum[j]);
}
for (int j = 0; j < 8; j++) {
free(person[i]->birthdate[j]);
}
}
return 0;
}
void inputValue(detailsOf **person, int maxSize) {
for (int i = 0; i < maxSize; i++) {
printf("Name of %d", i + 1);
scanf("%s", person[i]->name);
for (int j = 0; j < 8; j++) {
printf("Birth %d:", i + 1);
scanf("%d", person[i]->birthdate[j]);
}
for (int k = 0; k < 8; k++) {
printf("Phone %d:", i + 1);
scanf("%d", person[i]->phoneNum[k]);
}
}
printf("SUCCESS\n");
}
person = (detailsOf **)malloc(maxSize * sizeof(detailsOf **));
should be
person = malloc(maxSize * sizeof(detailsOf *));
Then, this allocated memory to hold pointers to detailsOf but you never allocate memory for each detailsOf
for(int i=0; i<maxSize; i++)
{
person[i]=malloc(sizeof(detailsOf));
}
Also your freeing of memory should be
for (int i = 0; i < maxSize; i++)
{
free(person[i]->name);
free(person[i]->phoneNum);
free(person[i]->birthdate);
free(person[i]);
}
free(person);
Remember while freeing just match your free calls with malloc calls.
Rule is simple -- a pointer is uninitialized until it has had a valid address assigned to it, or memory has been allocated within which to store things and the starting address for the new block of memory assigned to it.
You allocate maxSize pointers for person, but then fail to allocate a struct for each person[i] before allocating for name, etc..
So you must allocate a struct, e.g. pointer[i] = malloc (sizeof *pointer[i]) before attempting to allocate person[i]->name = calloc(21, sizeof(char ));, ...
Also note, if you allocate based on the size of the derefernced pointer -- you will never get your allocation wrong, (your allocation of person is only correct as the result of happy-accident), instead, e.g.
person = malloc (maxSize * sizeof *person);
...
person[i] = malloc (sizeof *person[i]);
(and note a [] or -> counts as a dereference)
person[i]->name = calloc (21, sizeof *person[i]->name);
There is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?
person = (detailsOf **)malloc(maxSize * sizeof(detailsOf **));
This allocates an array of double pointers to type detailsOf with array size as maxSize.
sizeof(detailsOf**) is the size of an address, it does not give you the size of your user-defined datatype detailsOf.
Also, double pointer means, it is an address location which will store the address of another pointer which points to the memory location of detailsOf
/* if you want to use double pointer then */
detailsOf **dptr; // two dimensional array of detailsOf */
detailsOf *sptr; /* one dimentional array of detailsOf */
/* This allocates the memory for storing 3 detailsOf struct data */
sptr = malloc(3 * sizeof(detailsOf));
dptr = &sptr;
/* Now to access double ptr */
for (int i = 0; i < 3; ++i) {
dptr[0][i].birthdate = malloc(3 * sizeof(int));
}
for (int i = 0; i < 3; ++i) {
dptr[0][i].birthdate[0] = i;
dptr[0][i].birthdate[1] = i + 10;
dptr[0][i].birthdate[2] = i + 1990;
}
for (int i = 0; i < 3; ++i) {
printf("%d\\", dptr[0][i].birthdate[0]);
printf("%d\\", dptr[0][i].birthdate[1]);
printf("%d\n", dptr[0][i].birthdate[2]);
}
/* Not to free the double pointer,
* you have to free the inner pointer first then the outer pointers
* Easy to remember is to free in reverse order of your allocation order
*/
for (int i = 0; i < 3; ++i) {
free(dptr[0][i].birthdate);
free(dptr[0]);
/* free(dptr); this is not needed in this example because
* dptr is pointer to address of a local variable,
* but if it points to address of another array of detailOf*
* then this free is needed
*/
}
In your case, you have just an array of pointer and not an array of double pointers.

Is it necessary to free sub-pointer before calling realloc on pointer-to-pointer array to shrink its size?

For example, I have this C code:
int len = 100;
int i;
// arr is pointer-to-pointer 2d array of char
char **arr = malloc(len * sizeof(char*));
for (i = 0; i < len; i++)
{
// Allocate the sub-pointer
arr[i] = malloc(len * sizeof(char));
...
}
...
// Is this part necessary?
for (i = 0; i < len; i++)
{
// Freeing the sub-pointer
free(arr[i]);
}
// Shrink the arr's size from 100 to 50
char** temp = realloc(arr, 50 * sizeof(char*));
...
Before to do realloc for arr to shrink its size (from 100 to 50), is it necessary to free the arr's sub-pointer?
for (i = 0; i < len; i++)
{
free(arr[i]);
}
Yes, you have to free all pointers if the reallocated array will have size that is less than the original size. For example
for (i = 50; i < len; i++)
{
free(arr[i]);
}
char** temp = realloc(arr, 50 * sizeof(char*));
C does not have destructors so you have manually to free all objects pointed to by the removed elements. Otherwise there will be memory leaks.

Freeing malloc of unknown size

I'm trying to free the malloc that is generated with a not fixed number of arrays.
char ** get_moves(){
// some code
char **moves = malloc(sizeof(char *) * k); // 'k', could ranges between 1~9
if (!moves){
return NULL;
}
for(int i = 0; i < k; i++){
moves[i] = malloc(82);
if (!moves[i]) {
free (moves);
return NULL;
}
// more code
return moves;
}
int main(){
//some code
char **res = get_moves(some_input);
//more code
for (int i = 0; i < (sizeof(res)/sizeof(res[0)); i ++){
free(res[i]);
}
free(res);
}
In one of the inputs to get_move, res should have 2 arrays but the sizeof(res)/sizeof(res[0) gives me just 1.
How is the proper way to handle this?
The only way is to keep track of the element count of the array, if you don't want to pass it to every function when passing the array, you can combine both pieces of information in a struct, like here
#include <stdlib.h>
struct ArrayOfStrings
{
int count;
char **data;
};
struct ArrayOfStrings get_moves()
{
struct ArrayOfStrings result;
char **moves;
// some code
result.count = 0;
result.data = malloc(sizeof(char *) * k); // 'k', could ranges between 1~9
if (result.data == NULL)
return result;
result.count = k;
moves = result.data;
for (int i = 0; i < k; i++)
{
moves[i] = malloc(82);
if (moves[i] == NULL)
{
/* also free succesfully allocated ones */
for (int j = i - 1 ; j >= 0 ; --j)
free(moves[j]);
free(moves);
}
result.count = 0;
result.data = NULL;
return result;
}
// more code
return result;
}
int main(){
//some code
struct ArrayOfStrings res = get_moves(some_input);
//more code
for (int i = 0; i < res.count ; i ++)
free(res.data[i]);
free(res.data);
return 0; // you should return from main.
}
sizeof is not for the length of an object's content but for the size of a data type, it is computed at compile time.
So in your case
sizeof(res) / sizeof(res[0]) == sizeof(char **) / sizeof(char *) == 1
since sizeof(char **) == sizeof(char *) it's just the size of a pointer.
sizeof(res)
Returns the sizeof(double-pointer);
So if you intend to get the number of pointers stored then you might not get this by doing what you are doing.
You need to do something like
for(i=0;i<k;i++) /* As I see you are allocating k no of pointer Keep track of it*/
free(res[i]);
free(res);
res is in fact not an array of arrays of char type. Instead it is a pointer to pointer to char type. sizeof(res) will give you the size of char**. You need to keep track of the number of allocations.
Since the maximum number of arrays to allocate is small (9), you can simplify your code by allocating the maximum number. Fill the unused elements with NULL:
#define MAX_K 9
char **moves = malloc(sizeof(char *) * MAX_K);
for(int i = 0; i < k; i++){
...
}
for(int i = k; i < MAX_K; i++){
moves[i] = NULL;
}
To deallocate, just ignore the NULL pointers:
for (int i = 0; i < MAX_K; i ++){
if (res[i])
free(res[i]);
}
free(res);

memory allocation - call by reference String-Array-Paramater

The question is how to correctly allocate/free the memory in this example:
void test(char*** array, int* count) {
*array = malloc(sizeof(char*) * MAX_ARRAY);
while (...) {
(*array)[i] = (char*)malloc(strlen(fooString));
}
}
call of the function:
char** array;
int count;
test(&array, &count);
// now free the memory - i think i have to?
for(i = 0; i < count; i++) {
free(array[i]); // <-- crash here
}
free(array);
It looks like that array[0] has a different address inside the test-function than outside. How can this be? Looks like i misunderstood sth, because the address of array is the same outside and inside the function.
Edit: The Problem is that i am not able to free the allocated memory (see "crash here" in code). Why? And how will it work?
Instead of
void test(char*** array, int* count) {
*array = malloc(sizeof(char*) * MAX_ARRAY);
while (...) {
(*array)[i] = (char*)malloc(strlen(fooString));
}
}
do
void test(char*** array, int count) {
*array = malloc(sizeof(char*) * count); // number of pointers
for (int i = 0; i < count; ++i)
{
(*array)[i] = malloc(strlen(fooString));
}
}
although i am not sure about what fooString is since you don't show the decl/def. Normally you would allocate one byte extra for the \0
(*array)[i] = malloc(strlen(fooString) + 1)
this seems to work
#include <stdio.h>
#include <inttypes.h>
#include <malloc.h>
#include <string.h>
char fooString[256];
void test(char*** array, int count)
{
int i = 0;
*array = malloc(sizeof(char*) * count);
for (i = 0; i < count; ++i)
{
(*array)[i] = malloc(strlen(fooString)+1);
}
}
int main()
{
char** array = NULL;
int count = 100;
int i = 0;
test(&array, count);
for(i = 0; i < count;++i)
{
free(array[i]);
}
free(array);
return 0;
}
For your particular problem:
You allocate (*array)[i] which is a char* to strlen(fooString) which is usually equivalent to sizeof(char) * strlen(fooString) : this is error prone. You should use sizeof(*((*array)[i])) in this case to be sure not to miss the correct type.
To free it, loop from i = 0 to i < MAX_ARRAY and call free(array[i])
What you put in place of ... in your code is very important.
In general, when allocating memory, be sure to respect these general ideas:
If a functions allocates memory it frees it itself except when it is needed outside afterwards.
If a function allocates memory needed outside afterwards, it does just this.
This allows for better code architecture and easier freeing of the memory.
For example:
First point:
void foo()
{
char *a;
a = malloc(sizeof(*a) * 5);
a[0] = 'a';
a[1] = 'b';
a[2] = 'c';
a[3] = 'd';
a[4] = 0; //or '\0' if you prefer
do_something_cool(a);
free(a);
}
The function foo allocates memory, processes it, and frees it.
Second point:
char *halfstrdup(char *str)
{
int len;
int i;
char *newstr;
len = strlen(str);
newstr = malloc(sizeof(*newstr) * len / 2)
for (i = 0; i < len; i++)
{
if ((i % 2) == 0)
newstr[i / 2] = str[i];
}
return (newstr);
}
void foo2()
{
char *half;
half = halfstrdup("Hello, world !");
do_something_cooler(half);
free(half);
}
The function halfstrdup just allocates and sets the memory you need and returns it, the function foo2 allocates memory through the use of halfstrdup, then uses it and frees it.
Do not forget to free before losing track of your pointers, for example after returning from foo or foo2, you won't be able to free the allocated memory.

Resources