I have a function which builds an array of strings (char*) .
After I finished using the array I want to free its memory but then I get a CrtIsValidHeapPointer Error.
Code:
int main(int argc, char * argv[])
{
char** arr = NULL;
creating_array(&arr); // Building the array
//free each string memory
for (size_t i = 0; i < 4; i++)
{
free(arr[i]);
}
// until here everything works fine :)
//free the array memory
free(arr); // Error CrtIsValidHeapPointer
return 0;
}
void creating_array(char*** pArr)
{
char** arr = (char**)malloc(4);
arr[0] = (char*)malloc(5 * sizeof(char));
strcpy(arr[0], "aaaa");
arr[1] = (char*)malloc(5 * sizeof(char));
strcpy(arr[1], "bbbb");
arr[2] = (char*)malloc(5 * sizeof(char));
strcpy(arr[2], "cccc");
arr[3] = (char*)malloc(5 * sizeof(char));
strcpy(arr[3], "dddd");
*pArr = arr;
}
Why does it happen?
Please try, in creating_array
char **arr ;
arr=(char **) calloc( 4 , sizeof(char *));
Here is the working code. It compiles and runs now.
Generally after freeing a pointer, people set it to NULL to avoid confusion (so that any time a pointer is not null it points to valid memory). That avoids bugs. Also it is legal to free(NULL), so you don't get into very severe and hard-to- debug problems that happen if you double-free an address.
One important point, is that in this case, the parenthesis in this case (*pArr)[2] are important, to override the operator precedence in C. If you try *pArr[2] it assumes you mean to de-reference the pointer stored at element [2]. (*pArr)[2] means return element at element to from the the location at the address pointed to by pArr. The reason C assumes the other case and that you need parens in this case is that the other use is much much more common, so it is convenient.
Note: ALWAYS check return values for malloc() and function calls and have a strategy to catch and log errors. Otherwise as you start writing bigger programs you will find them extremely difficult, troublesome or nearly impossible to debug.
Another thing is to create named constants instead of literals, because then it is clear what the number is and how it is used, and if that number is needed in more than one place it can be changed in one place. It makes the program easier to read and understand.
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#define STRING_COUNT 4
char **create_array(char ***pArr);
int
main()
{
char **arr = NULL;
if (create_array(&arr) == NULL) {
fprintf(stderr, "out of memory - exiting\n");
return -1;
}
for (size_t i = 0; i < STRING_COUNT; i++) {
printf("%s\n", arr[i]);
}
for (size_t i = 0; i < STRING_COUNT; i++) {
free(arr[i]);
arr[i] = NULL;
}
free(arr);
return 0;
}
char **
create_array(char ***pArr)
{
if ((*pArr = malloc(STRING_COUNT * sizeof (char **))) == NULL) {
return NULL;
}
if (((*pArr)[0] = strdup("aaaa")) == NULL) {
return NULL;
}
if (((*pArr)[1] = strdup("bbbb")) == NULL) {
free((*pArr)[0]);
*pArr[0] = NULL;
return NULL;
}
if (((*pArr)[2] = strdup("bbbb")) == NULL) {
free((*pArr)[0]);
*pArr[0] = NULL;
free((*pArr)[1]);
*pArr[1] = NULL;
return NULL;
}
if (((*pArr)[3]= strdup("bbbb")) == NULL) {
free((*pArr)[0]);
*pArr[0] = NULL;
free((*pArr)[2]);
*pArr[1] = NULL;
free((*pArr)[2]);
*pArr[2] = NULL;
return NULL;
}
return *pArr;
}
Related
To allocate and free a single string in C, I do the following:
char[10] stringToCopy = "CopyString";
int length = strlen(stringToCopy) + 1;
char* CopiedString = malloc(length);
strcpy(CopiedString, stringToCopy, length);
printf("DatabasePath=%s\r\n", CopiedString);
free(CopiedString);
In my program, I need to copy such strings to a char** datatype. I need help in writing such a program. I am using a third party API which has a structure with this char** field entry.
I am not aware of how to allocate memory to this datatype and then copy the CopiedString into a list of such values. And also how to free the value after usage.
Allocating memory:
char **arr = malloc(r * sizeof(char *));
for (i=0; i<r; i++)
{
arr[i] = malloc(c * sizeof(char));
}
Freeing memory:
for (i=0; i<r; i++)
{
free(arr[i]);
}
free(arr);
I am not aware of how to allocate memory to this datatype ....
Follows is a useful C idiom for allocating.
size_t number_in_array = ...;
ptr = malloc(sizeof *ptr * number_in_array);
if (ptr == NULL) {
puts("Allocation failed");
} else {
puts("Success");
// Use ptr
free(ptr): // **
}
...
free(ptr): // **
// ** free(ptr) in 1 of 2 places.
Notice there is no need to code the type of the pointer in the allocation: ptr = malloc(sizeof *ptr * number_in_array);. This is easier to code right, review and maintain than attempting to code the type.
... then copy the CopiedString into a list of such values.
You already have good code to form a copied string. Make a helper function. Below is OP's with some improvements. Also research the common strdup() function.
char *my_strdup(const char *stringToCopy) {
size_t size = strlen(stringToCopy) + 1;
char* CopiedString = malloc(size);
if (CopiedString) {
memcpy(CopiedString, stringToCopy, size);
}
return CopiedString;
}
And also how to free the value after usage.
size_t number_in_array = 3;
char **ptr = malloc(sizeof *ptr * number_in_array);
if (ptr == NULL) {
puts("Allocation failed");
} else {
ptr[0] = my_strdup("Hello");
ptr[1] = my_strdup(" ");
ptr[2] = my_strdup("World");
// Use ptr (could check for ptr[] allocation failures first)
for (size_t i = 0; i < number_in_array; i++) {
free(ptr[i]);
}
free(ptr):
}
You can use strdup to create malloced string in c.
char ** presult = NULL;
for double pointer "presult" we can assign data like this.
if (presult) {
*presult = strdup("CopyString");
}
Sample code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int copy_data(char ** p) {
if (p) {
*p = strdup("Test data");
}
return 0;
}
int main () {
char * p = NULL;
copy_data(&p);
if (p) {
printf("daat : %s\n", p);
// free if not used
free(p);
p = NULL;
}
return 0;
}
Go through the below program which explains how to allocate memory for char** and also how to free the same.
Comments are in lined for understanding, please get back in case of any clarification needed.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define NUMBER_OF_STRINGS 5
#define MAX_LEN_OF_STRING 50
void printStrings_array(char ex_strings[][MAX_LEN_OF_STRING], int nstrings);
char** allocMemForStrings(int nStrings);
void printStrings_ptr(char** strings, int nStrings);
int main()
{
// example list of string for which we are going to allocate memory and store in char**
char ex_strings[NUMBER_OF_STRINGS][MAX_LEN_OF_STRING] =
{
"This is the First String",
"This is the Second String",
"This is the Third String",
"This is the Fourth String",
"This is the Fifth String",
};
printf("contents of char[][] \n");
printStrings_array(ex_strings, NUMBER_OF_STRINGS);
// list_of_strings is a variable which points to list of strings
char** list_of_strings = NULL;
// allocating memory for list of strings
if ( list_of_strings = allocMemForStrings(NUMBER_OF_STRINGS))
{
int i = 0;
printf("got %p for list_of_strings\n", (void*)list_of_strings);
while(i < NUMBER_OF_STRINGS)
{
size_t len = strlen(ex_strings[i])+1;
// allocate memory for each string as per its length
list_of_strings[i] = malloc(len);
printf("got %p for string %d\n", (void*)list_of_strings[i], i);
memset(list_of_strings[i], 0, len);
strncpy(list_of_strings[i], ex_strings[i], len);
i++;
}
printf("contents of char** \n");
printStrings_ptr(list_of_strings, NUMBER_OF_STRINGS);
// free ing the memory for char **
// first we need to free the memory for each of the strings pointed by the list_of_strings variable.
i = 0;
while(i < NUMBER_OF_STRINGS)
{
printf("\n freeing %p ", (void*)list_of_strings[i]);
free(list_of_strings[i]);
list_of_strings[i] = NULL;
i++;
}
//now free the list_of_strings pointer
printf("\n finally freeing %p ", (void*)list_of_strings);
free(list_of_strings);
// to avoid dangling pointers, its best practice to set the pointers = NULL after free.
list_of_strings = NULL;
}
else
{
printf("cannot allocate memory for strings\n");
}
return 0;
}
void printStrings_array(char ex_strings[][MAX_LEN_OF_STRING], int nstrings)
{
for(int i = 0; i< nstrings;i++)
printf(" %s\n", ex_strings[i]);
}
void printStrings_ptr(char** strings, int nStrings)
{
for(int i = 0; i< nStrings;i++)
printf(" %s\n", strings[i]);
}
char** allocMemForStrings(int nStrings)
{
// need to have memory to store nStrings
return malloc(nStrings * sizeof (char*));
}
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int isPresent(char *array[], char *string, int dimension) {
for (int i=0; i<dimension; i++) {
if (strcmp(array[i], string) != 0) {
continue;
} else {
return 1;
}
}
return 0;
}
int main(int argc, char *argv[]) {
int dim = 0;
char **without_duplicates = malloc(dim * sizeof(char *));
for (int i=1; i<argc; i++) {
if (!isPresent(without_duplicates, argv[i], dim)) {
realloc(without_duplicates, (dim + 1) * sizeof(char *));
without_duplicates[dim] = malloc((strlen(argv[i]) + 1) * sizeof(char));
strcpy(without_duplicates[dim], argv[i]);
printf("%s\n", without_duplicates[dim]);
dim++;
} else {
continue;
}
}
printf("%s\n", "Not duplicated arguments:");
for (int i=0; i<dim; i++) {
printf("%s\n", without_duplicates[i]);
}
return 0;
}
I execute the code: ./a.out rome turin rome milan venice milan florence.
But obtain segmentation fault error.
I tried to debug the code and it works until a certain point.
For example it copies rome, turin, discards rome, copies milan, but not venice and the other cities.
If it works for some cities why not with the others?
The program has an unexpected behavior, and crashes at different points with different arguments.
I don't know the number of arguments and their length, so the new array without the duplicates must be allocated dynamically.
In your code, you are not assigning the return value of realloc to any variable
realloc(without_duplicates, (dim + 1) * sizeof(char *));
According to cppreference:
On success, returns the pointer to the beginning of newly allocated memory. The returned pointer must be deallocated with free()or realloc(). The original pointer ptr is invalidated and any access to it is undefined behavior (even if reallocation was in-place).
On failure, returns a null pointer. The original pointer ptr remains valid and may need to be deallocated with free() or realloc().
Try doing something like
char** temp = realloc(without_duplicates, (dim + 1) * sizeof(char *));
if(temp != NULL) {
without_duplicates = temp
}
else {
//handle the unsuccessful allocation
}
Note: Similarly you need to check for malloc() whether the memory allocation was successful or not.
Try this: I also allowed myself to remove some useless statements within your code, hope you dont mind
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int isPresent(char *array[], char *string, int dimension)
{
for (int i=0; i<dimension; i++)
{
if (strcmp(array[i], string) == 0)
return 1;
}
return 0;
}
int main(int argc, char *argv[])
{
int dim = 0;
char ** without_duplicates = malloc(dim * sizeof(char *));
for (int i=1; i<argc; i++)
{
if (!isPresent(without_duplicates, argv[i], dim))
{
without_duplicates = realloc(without_duplicates, (dim + 1) * sizeof(char *));
without_duplicates[dim] = malloc((strlen(argv[i]) + 1) * sizeof(char));
strcpy(without_duplicates[dim], argv[i]);
dim++;
}
}
printf("%s\n", "Not duplicated arguments:");
for (int i=0; i<dim; i++)
{
printf("%s\n", without_duplicates[i]);
}
return 0;
}
Your problem was simply not getting the return value out of realloc function,
C is not what one may consider as a high-level programming language... If reallocating some memory, the variable storing that address must be aware of the new address of the new allocated memory hence you must store it:
without_duplicates = realloc(without_duplicates, (dim + 1) * sizeof(char *));
This caused segmentation fault because before storing the new allocated address you simply jumped to an address that does not exist within the context of your process and attempt store some data in it, that in result causes segmentation fault
I thought I understood how dynamic memory worked basically, but I did the following. I use this function to allocate dynamic memory:
int get_alota_mem(char*** const ptr)
{
int result = EXIT_SUCCESS;
bool success = true;
if (success && (*ptr = calloc(10, sizeof **ptr)) == NULL)
{
result = EXIT_FAILURE;
success = false;
}
for (int i = 0; i < 10; i++)
{
if (success && ((*ptr)[i] = calloc(20, sizeof ***ptr)) == NULL)
{
result = EXIT_FAILURE;
success = false;
}
}
return result;
}
I use this function to free the allocated dynamic memory:
void free_alota_mem(char** const ptr)
{
for (int i = 0; i < 10; i++)
{
free(ptr[i]); // segfault!
ptr[i] = NULL;
}
free(ptr);
}
In between those two calls I can use the memory and don't encounter any segfaults. But when I try to free the memory, I get a segfault with the first value I try to free.
I know I could just do char* ptr[10] and just use an auto allocated array instead of a dynamically allocated pointer, which would save me some hassle, but I wanted to try and make this work.
EDIT:
My main:
int main(void)
{
char** mem = NULL;
get_alota_mem(&mem);
mem[0] = "Hello";
mem[1] = "world";
free_alota_mem(mem);
}
You tried to free string literals. Passing pointer that is not NULL and not what is allocated via memory management functions such as malloc() to free() will invoke undefined behavior.
To copy strings, use strcpy() function.
#include <string.h>
int main(void)
{
char** mem = NULL;
get_alota_mem(&mem);
strcpy(mem[0], "Hello");
strcpy(mem[1], "world");
free_alota_mem(mem);
}
I was playing with double pointers in C and was wondering if I create a function that initializes the table, it crashes on going back to main when I try to make use of the memory allocated by InitStringTable. I believe a simple fix is to make strTable global and then I believe its OK, but I prefer not to do so as this is more of a learning exercise for me in passing the table around for modification i.e. I should be able to modify strTable from main or another function modifyTable after InitStringTable.
Thanks for any help you can give.
int main()
{
char** strTable;
// Allocates memory for string table.
InitStringTable(strTable);
// Below lines should be able to copy strings into newly allocated table.
// Below lines cause crash however.
strcpy(strTable[0], "abcdef");
strcpy(strTable[1], "xy");
}
// Allocates memory for the string table. This function should create a table
// of size 10 strings with each string 50 chars long. The code compiles fine.
void InitStringTable(char** table)
{
int i = 0;
table = (char**)malloc(sizeof(char)*10);
for(i = 0; i < 10; i++)
{
table[i] = (char*)malloc(sizeof(char)*50);
}
for(i = 0; i < 10; i++)
{
memset(table[i], 0, 50);
}
strcpy(table[0], "string1");
}
C is pass by value.
The value assigned to table is lost on returning from InitStringTable().
Also when allocating pointers to char ask for room for pointers to char.
So this:
... = (char**)malloc(sizeof(char)*10);
shall at least be (assuming C):
... = malloc(sizeof(char*)*10);
A possible approach to this would be:
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int InitStringTable(char *** ppptable, const size_t n, const size_t l)
{
int result = 0;
if (NULL == ppptable)
{
result = -1;
errno = EINVAL;
}
else
{
(*ppptable) = malloc(n * sizeof(**ppptable));
if (NULL == (*ppptable))
{
result = -1;
}
else
{
size_t i = 0;
for(; i < n; ++i)
{
(*ppptable)[i] = calloc(l, sizeof(*(*ppptable)[i]));
if (NULL == (*ppptable)[i])
{
result = -1;
/* Failing in the middle requires clean-up. */
for (; i > 0; --i)
{
free((*ppptable)[i-1]);
}
free(*ppptable);
(*ppptable) = NULL;
break;
}
}
}
}
return result;
}
Call it like this:
#include <stdlib.h>
#include <stdio.h>
int InitStringTable(char *** ppptable, const size_t n, const size_t l);
int main(void)
{
int result = EXIT_SUCCESS;
char ** strTable = NULL;
if ( -1 == InitStringTable(&strTable, 10, 42)) //* Allocate array with 10 "strings" à 42 chars. */
{
perror("InitStringTable() failed");
result = EXIT_FAILURE;
}
else
{
strcpy(strTable[0], "abcdef");
strcpy(strTable[1], "xy");
}
return result;
}
And no, I won't get into this ridiculous "You don't wanna be a 3-star-programmer!" discussion.
You have a pointer issue.
It's like if you say:
void inc(int a){
a++;
}
int main(){
int a = 0;
inc(a);
printf ("%d\n", a); // will display 0, not 1
}
does not work.
You must pass &strTable instead of strTable as InitStringTable argument, and change other things in InitStringTable consequently ..
Or just do strTable = InitStringTable(); , and return a char** from InitStringTable.
The lines below InitStringTable() crash, because they are trying to perform operations
on a memory address that is neither in the same scope as theirs nor have any reference to
that memory address.
The function InitStringTable() allocates memory to the table, but cannot be accessed by the
calling function (here main), because the memory is local to the function in which it
allocated.
Therefore in order to use the same memory address for operations in the
calling function you must pass a reference of that address to the calling function.
In your program you can do it as under :
Declare the function as :-
char **InitStringTable(char **);
int main()
{
char** strTable;
strTable = InitStringTable(strTable);
strcpy(strTable[0], "abcdef");
strcpy(strTable[1], "xy");
}
char **InitStringTable(char** table)
{
int i = 0;
table = (char**)malloc(sizeof(char)*10);
for(i = 0; i < 10; i++)
{
table[i] = (char*)malloc(sizeof(char)*50);
}
for(i = 0; i < 10; i++)
{
memset(table[i], 0, 50);
}
strcpy(table[0], "string1");
/* after the function has finished its job, return the address of the table */
return table;
}
i have a problem with the initialization of the values inside the first dynamic array of pointers
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char*** GetIndexes()
{
int n = 0;
char ***index;
printf("please insert the number of words you want to add to dictionary\n");
scanf("%d", &n);
index = (char***)calloc(n, sizeof(char));
if (index == NULL)
{
printf("allocation Failed");
return;
}
return index;
}
char** GetDefinitions()
{
int n = 0;
char **definition;
printf("please insert the number of defintions you want to add to the word\n");
scanf("%d", &n);
definition = (char**)calloc(n+1, sizeof(char));
if (definition == NULL)
{
printf("allocation failed");
return;
}
return definition;
}
int main()
{
char *** dptr = GetIndexes();
if (dptr == NULL)
{
printf("memory Allocation failed");
}
int indexcount = sizeof(dptr) / sizeof(char),i;
for (i = 0; i < indexcount; i++)
{
printf("word number %d\n", i + 1);
*dptr[i] = GetDefinitions();
}
printf("%p",dptr);
}
i tried running the debugger in VS2013 and after i enter the number of defintions i want it crashed with this message:
Unhandled exception at 0x01103FB0 in ConsoleApplication1.exe: 0xC0000005: Access violation writing location 0x00000000.
i missed an allocation of something but i cant quite figure out what i missed,
thanks in advance
Your program is very broken
You allocate n char ***s but only request space for n chars and also do it for char **, to prevent this kind of mistake you may use the sizeof operator this way
char ***index;
index = calloc(n, sizeof(*index));
and
char **definition;
definition = calloc(n, sizeof(*definition));
and as you see casting calloc makes it harder and it's not necessary.
You have a return statement that doesn't return anything an GetIndexes() as well as one in GetDefinitions.
They should return NULL if you want to handle failure in the caller function
return NULL;
You erroneously use the sizeof operator to determine the number of char *** pointer allocated in
int indexcount = sizeof(dptr) / sizeof(char)
this will be either 4 or 8 depending on the architecture i.e. the size of a pointer divided by 1 sizeof(char) == 1 always.
You can't compute that value, you simply have to keep track of it. The size
You dereference the triple pointer twice and try to assign a double pointer to it
*dptr[i] = GetDefinitions();
here the operator precedence is also an issue, but regardless of that, this is wrong, may be what you meant was
dptr[i] = GetDefinitions();
This is not going to make your program crash, but it's certainly important to free all malloced pointers before exiting the program.
Here is a suggestion for your code to work, ignore it's purpose since it's not clear what you are trying to do
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char ***GetIndexes(unsigned int *count)
{
char ***index;
printf("please insert the number of words you want to add to dictionary > ");
scanf("%u", count);
index = calloc(*count, sizeof(*index));
if (index == NULL)
{
printf("allocation Failed");
return NULL;
}
return index;
}
char **GetDefinitions(unsigned int *count)
{
char **definition;
printf("please insert the number of defintions you want to add to the word > ");
scanf("%u", count);
definition = calloc(*count + 1, sizeof(*definition));
if (definition == NULL)
{
printf("allocation failed");
return NULL;
}
return definition;
}
int main()
{
unsigned int indexCount, i;
char ***dptr = GetIndexes(&indexCount);
if (dptr == NULL)
{
printf("memory Allocation failed");
}
for (i = 0; i < indexCount; i++)
{
unsigned int definitionsCount;
printf("Word number %u\n", i + 1);
dptr[i] = GetDefinitions(&definitionsCount);
if (dptr[i] != NULL)
{
/* use dptr[i] here or maybe somewhere else, but when you finish */
free(dptr[i]);
}
}
printf("%p", dptr);
/* now if you are done using dptr */
free(dptr);
return 0;
}
As already mentioned in the comment this is a very bad idea and just using double pointers is good here. But the below fixes should be done if you want to use pointers to allocate memory
index = calloc(n, sizeof(char));
should be
index = calloc(n, sizeof(char **));
and
definition = calloc(n+1, sizeof(char));
should be
definition = calloc(n+1, sizeof(char *));