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);
}
Related
This code is meant to copy an int array with count elements to a newly applied memory area in the heap.
int copy(int *array ,int count){
int i;
int *myarray = (int*)malloc(count*sizeof(int));
if (myarray == NULL)
return -1;
for(int i = 0;i<count;i++)
{
myarray[i]=array[i];
}
return count;
i think maybe it forgets to use free() after using the malloc() function to free the memory but this code is meant to copy array element in the memory.so whether i am right ? If no, what is the really bug?
This function leaks memory.
myarray contains a pointer to allocated memory which contains a copy of the data in array. However, this pointer is not used in any way when the function returns so the pointer to the allocated memory is lost.
The function should return a pointer to this memory so that it can be used.
int *copy(int *array ,int count){
int i;
int *myarray = malloc(count*sizeof(int));
if (myarray == NULL)
return -1;
for(int i = 0;i<count;i++)
{
myarray[i]=array[i];
}
return myarray;
}
Note that it will be the responsibility of the calling function to free the memory when it is done with it.
Your copy function functions allocates memory and then copies the elements of the array to that newly allocated memory. So far so good, but then you simply throw away the pointer to that newly allocated memory.
It's like copying a letter by hand, putting the copy into a safe, closing the safe with the key and then throw the key away. Now the copy of the letter is in the safe, but you can't access it any more.
You probably want something like this:
...
int *copy(int *array, int count) // return a pointer to int, not an int
{
int *myarray = malloc(count*sizeof(int)); // (int*) cast is not needed
if (myarray == NULL)
return NULL; // return NULL if malloc fails
for(int i = 0; i < count; i++)
{
myarray[i] = array[i];
}
return myarray; // return pointer to newly allocated memory
}
...
int source[] = {1,2,3,4,5};
int *destination = copy(source, 5);
if (destination == NULL)
{
// handle error
}
// now destination points the the copy of the array
for (int i = 0; i < 5; i++)
{
printf("%d\n", destination[i]);
}
...
free(destination); // free allocated memory when you're done with it
...
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*));
}
Why does this program result in a segmentation fault? I'm trying to have an array of pointers that is dynamically allocated memory so that I can have an array of strings.
I've searched for similar issues like How to pass a double pointer to a function without segmentation fault C language
Please explain why it it seg-faulting
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void mem_alloc(char* p, char** dp);
int entries = 0;
int mem_allocated = 0;
int main() {
char* p = "ksdfahj93qhf9";
char* p1 = "siodfnrieopq";
char* p2 = "erf9ih94gri9g";
char** dp = NULL;
mem_alloc(p, dp);
mem_alloc(p1, dp);
mem_alloc(p2, dp);
for(int i = 0; i < entries; i++) {
printf("%s", dp[i]);
}
}
void mem_alloc(char *p, char** dp) {
if(entries == mem_allocated)
if(mem_allocated == 0)
mem_allocated = 3;
void** temp = realloc(dp, mem_allocated * (sizeof(p)));
if(!temp)
perror("Memory allocation failed!");
dp = (char**) temp;
strcpy(dp[entries++], p);
}
In your mem_alloc function you modify the function parameter dp. This modification is not visible outside of the function. As a result, the dp in main never changes and is still set to NULL.
You need to pass the address of this variable to the function, then in the function you dereference that pointer to change it.
So you function becomes:
void mem_alloc(char *p, char ***dp) {
if(entries == mem_allocated)
if(mem_allocated == 0)
mem_allocated = 3;
char **temp = realloc(*dp, mem_allocated * (sizeof(p)));
if(!temp)
perror("Memory allocation failed!");
*dp = temp;
(*dp)[entries++] = strdup(p); // space also needs to be allocated for the new string
}
And you call it like this:
mem_alloc(p, &dp);
Two errors. First is the one mentioned by dbush.
Second, you are not allocating space for your string before you copy it. You can use strndup() instead of strcpy().
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;
}
Okay, imagine I have a char**, would this be the correct way to allocate memory?
I mean: allocate memory for the char** itself and then for each char*...
char** fraseUsuario = NULL;
int length = 100, i = 0;
fraseUsuario = (char **) malloc(sizeof (char*)); //Not pretty sure
for (i = 0; i < 3; i++) {
fraseUsuario[i] = (char *) malloc(length * sizeof (char));
if (fraseUsuario[i] == NULL) {
printf("error\n");
return -1;
}
gets(fraseUsuario[i]);
}
for (i = 0; i < 3; i++) {
printf("%s\n", fraseUsuario[i]);
free(fraseUsuario[i]);
}
And btw, how exactly does free() work? I mean, when I call it at the end, with the debugger it seems as if it does "nothing", if "Hello" is stored in the array, it will continue to be stored there after the free call... is that the normal behavior?
What do you mean allocate memory for the char ** itself? You allocate memory for a variable on the stack when you define it. The following statement defines (allocates memory) fraserUsuario and initializes it to NULL.
char **fraseUsuario = NULL;
I think what you probably meant is how to dynamically allocate an array of char **, i.e., pointer to a pointer to a character. Then you again dynamically allocate an array for each element of the previous allocated array. Do not use gets. It's deprecated and unsafe to use. Use fgets instead. Also, please don't cast the result of malloc. You don't get any benefit and you can run into error if you forget to include the header stdlib.h which contains its prototype. Here's how you do it.
char **fraseUsuario = NULL;
int max_string_len = 100 + 1; // maximum string length. +1 for null byte
int num_string = 3; // number of strings to read
int i, j;
fraseUsuario = malloc(num_string * sizeof *fraseUsuario);
if(fraseUsuario == NULL) { // check for NULL
// handle the case
printf("not enough memory\n");
return -1;
}
for(i = 0; i < num_string; i++) {
fraseUsuario[i] = malloc(max_string_len * sizeof(char));
if(fraseUsuario[i] == NULL) { // check for NULL
printf("not enough memory\n");
for(j = 0; j < i; j++)
free(fraseUsuario[j]); // free memory before returning
free(fraseUsuario); // free memory before returning
return -1;
}
if(fgets(fraserUsuario[i], max_string_len, stdin) == NULL) {
// reading string failed
*fraserUsuario[i] = '\0'; // empty string
}
}
for(i = 0; i < 3; i++) {
printf("%s\n", fraseUsuario[i]);
free(fraseUsuario[i]); // free memory allocated for strings
}
free(fraseUsuario); // free memory allocated for pointers to strings
fraseUsuario = NULL;
When you call free on a memory address which you got by a call to malloc, the memory block is returned to the free pool on the heap. This memory block can then later be reused by malloc. Once you free memory, you have given up your ownership of it. It no longer belongs to you and attempting to use it is illegal and will result in undefined behaviour and likely segfault.
You only allocate memory for one char* but use three.
To fix this do:
#define STR_MAXIMUM (3)
...
size_t length = 100, i = 0; /* No need to use a signed type.
size_t is meant as index and size type. */
char ** fraseUsuario = malloc(STR_MAXIMUM * sizeof(*fraseUsuario));
for (i = 0; i < STR_MAXIMUM; ++i)
{
fraseUsuario[i] = malloc(length * sizeof(*fraseUsuario));
...
Also add error checking to system calls.
Also^2: Do not use gets() as there is no way for the compiler or the machine to prevent the buffer passed in from overflowing. Use fgets() instead.
fgets(fraseUsuario[i], length, stdin);