Free() a safe-copied string array crashes? - arrays

I am trying to run the following C program on an SoC platform (baremetal application).
I have a couple of string arrays, defined as
char *init_array[] = { "foo", "bar bar" }
I know this works as an array of char arrays : *init_array[0] returns the 'f' character, init_array[0] returns the first address of "foo" and &init_array[0] returns the adress where the first address of "foo" is saved. The program I work with is based on that definition, so I am not supposed to change it.
Those arrays are going into a loop, in which there may or may not occur an external alteration. At the following iteration, the array must not carry the 'error'.
One of the solutions I've got was to keep two copies of those arrays, the ones I'm gonna use and ones that will initialize them.
Obviously, this has to be "safe-copied", in order to avoid using the same addresses. I have achieved this, with the following code:
char *my_array[2];
for (int i = 0; i < 2; i++) {
my_array[i] = malloc(strlen(init_array[i]) + 1);
memcpy(my_array[i], init_array[i],
strlen(init_array[i]) + 1);
}
The use of malloc() here (which I would rather avoid, if it's possible) demands the use of free() at the end of every iteration:
for (int i = 0; i < 2; i++) {
// i know it crashes somewhere here
free(my_array[i]);
my_array[i] = NULL; //this is supposed to tackle the issue of the same pointer being freed twice(?)
And it works perfectly, for a small number of iterations. Then, the program crashes, and I have to reset the platform I'm working on. As I mention above, I know it crashes somewhere in the last loop.
I've also read that:
Crashes in malloc(), calloc(), realloc(), or free() are almost always
related to heap corruption, such as overflowing an allocated chunk or
freeing the same pointer twice.
I really can't figure out what I'm doing wrong. Is this a heap corruption issue and how can I handle it or am I wrong from the start?

Related

Returning an array from function in C

I've written a function that returns an array whilst I know that I should return a dynamically allocated pointer instead, but still I wanted to know what happens when I am returning an array declared locally inside a function (without declaring it as static), and I got surprised when I noticed that the memory of the internal array in my function wasn't deallocated, and I got my array back to main.
The main:
int main()
{
int* arr_p;
arr_p = demo(10);
return 0;
}
And the function:
int* demo(int i)
{
int arr[10] = { 0 };
for (int i = 0; i < 10; i++)
{
arr[i] = i;
}
return arr;
}
When I dereference arr_p I can see the 0-9 integers set in the demo function.
Two questions:
How come when I examined arr_p I saw that its address is the same as arr which is in the demo function?
How come demo_p is pointing to data which is not deallocated (the 0-9 numbers) already in demo? I expected that arr inside demo will be deallocated as we got out of demo scope.
One of the things you have to be careful of when programming is to pay good attention to what the rules say, and not just to what seems to work. The rules say you're not supposed to return a pointer to a locally-allocated array, and that's a real, true rule.
If you don't get an error when you write a program that returns a pointer to a locally-allocated array, that doesn't mean it was okay. (Although, it means you really ought to get a newer compiler, because any decent, modern compiler will warn about this.)
If you write a program that returns a pointer to a locally-allocated array and it seems to work, that doesn't mean it was okay, either. Be really careful about this: In general, in programming, but especially in C, seeming to work is not proof that your program is okay. What you really want is for your program to work for the right reasons.
Suppose you rent an apartment. Suppose, when your lease is up, and you move out, your landlord does not collect your key from you, but does not change the lock, either. Suppose, a few days later, you realize you forgot something in the back of one closet. Suppose, without asking, you sneak back to try to collect it. What happens next?
As it happens, your key still works in the lock. Is this a total surprise, or mildly unexpected, or guaranteed to work?
As it happens, your forgotten item still is in the closet. It has not yet been cleared out. Is this a total surprise, or mildly unexpected, or guaranteed to happen?
In the end, neither your old landlord, nor the police, accost you for this act of trespass. Once more, is this a total surprise, or mildly unexpected, or just about completely expected?
What you need to know is that, in C, reusing memory you're no longer allowed to use is just about exactly analogous to sneaking back in to an apartment you're no longer renting. It might work, or it might not. Your stuff might still be there, or it might not. You might get in trouble, or you might not. There's no way to predict what will happen, and there's no (valid) conclusion you can draw from whatever does or doesn't happen.
Returning to your program: local variables like arr are usually stored on the call stack, meaning they're still there even after the function returns, and probably won't be overwritten until the next function gets called and uses that zone on the stack for its own purposes (and maybe not even then). So if you return a pointer to locally-allocated memory, and dereference that pointer right away (before calling any other function), it's at least somewhat likely to "work". This is, again, analogous to the apartment situation: if no one else has moved in yet, it's likely that your forgotten item will still be there. But it's obviously not something you can ever depend on.
arr is a local variable in demo that will get destroyed when you return from the function. Since you return a pointer to that variable, the pointer is said to be dangling. Dereferencing the pointer makes your program have undefined behavior.
One way to fix it is to malloc (memory allocate) the memory you need.
Example:
#include <stdio.h>
#include <stdlib.h>
int* demo(int n) {
int* arr = malloc(sizeof(*arr) * n); // allocate
for (int i = 0; i < n; i++) {
arr[i] = i;
}
return arr;
}
int main() {
int* arr_p;
arr_p = demo(10);
printf("%d\n", arr_p[9]);
free(arr_p) // free the allocated memory
}
Output:
9
How come demo_p is pointing to data which is not deallocated (the 0-9 numbers) already in demo? I expected that arr inside demo will be deallocated as we got out of demo scope.
The life of the arr object has ended and reading the memory addresses previously occupied by arr makes your program have undefined behavior. You may be able to see the old data or the program may crash - or do something completely different. Anything can happen.
… I noticed that the memory of the internal array in my function wasn't deallocated…
Deallocation of memory is not something you can notice or observe, except by looking at the data that records memory reservations (in this case, the stack pointer). When memory is reserved or released, that is just a bookkeeping process about what memory is available or not available. Releasing memory does not necessarily erase memory or immediately reuse it for another purpose. Looking at the memory does not necessarily tell you whether it is in use or not.
When int arr[10] = { 0 }; appears inside a function, it defines an array that is allocated automatically when the function starts executing (or at certain times within the function execution if the definition is in some nested scope). This is commonly done by adjusting the stack pointer. In common systems, programs have a region of memory called the stack, and a stack pointer contains an address that marks the end of the portion of the stack that is currently reserved for use. When a function starts executing, the stack pointer is changed to reserve more memory for that function’s data. When execution of the function ends, the stack pointer is changed to release that memory.
If you keep a pointer to that memory (how you can do that is another matter, discussed below), you will not “notice” or “observe” any change to that memory immediately after the function returns. That is why you see the value of arr_p is the address that arr had, and it is why you see the old data in that memory.
If you call some other function, the stack pointer will be adjusted for the new function, that function will generally use the memory for its own purposes, and then the contents of that memory will have changed. The data you had in arr will be gone. A common example of this that beginners happen across is:
int main(void)
{
int *p = demo(10);
// p points to where arr started, and arr’s data is still there.
printf("arr[3] = %d.\n", p[3]);
// To execute this call, the program loads data from p[3]. Since it has
// not changed, 3 is loaded. This is passed to printf.
// Then printf prints “arr[3] = 3.\n”. In doing this, it uses memory
// on the stack. This changes the data in the memory that p points to.
printf("arr[3] = %d.\n", p[3]);
// When we try the same call again, the program loads data from p[3],
// but it has been changed, so something different is printed. Two
// different things are printed by the same printf statement even
// though there is no visible code changing p[3].
}
Going back to how you can have a copy of a pointer to memory, compilers follow rules that are specified abstractly in the C standard. The C standard defines an abstract lifetime of the array arr in demo and says that lifetime ends when the function returns. It further says the value of a pointer becomes indeterminate when the lifetime of the object it points to ends.
If your compiler is simplistically generating code, as it does when you compile using GCC with -O0 to turn off optimization, it typically keeps the address in p and you will see the behaviors described above. But, if you turn optimization on and compile more complicated programs, the compiler seeks to optimize the code it generates. Instead of mechanically generating assembly code, it tries to find the “best” code that performs the defined behavior of your program. If you use a pointer with indeterminate value or try to access an object whose lifetime has ended, there is no defined behavior of your program, so optimization by the compiler can produce results that are unexpected by new programmers.
As you know dear, the existence of a variable declared in the local function is within that local scope only. Once the required task is done the function terminates and the local variable is destroyed afterwards. As you are trying to return a pointer from demo() function ,but the thing is the array to which the pointer points to will get destroyed once we come out of demo(). So indeed you are trying to return a dangling pointer which is pointing to de-allocated memory. But our rule suggests us to avoid dangling pointer at any cost.
So you can avoid it by re-initializing it after freeing memory using free(). Either you can also allocate some contiguous block of memory using malloc() or you can declare your array in demo() as static array. This will store the allocated memory constant also when the local function exits successfully.
Thank You Dear..
#include<stdio.h>
#define N 10
int demo();
int main()
{
int* arr_p;
arr_p = demo();
printf("%d\n", *(arr_p+3));
}
int* demo()
{
static int arr[N];
for(i=0;i<N;i++)
{
arr[i] = i;
}
return arr;
}
OUTPUT : 3
Or you can also write as......
#include <stdio.h>
#include <stdlib.h>
#define N 10
int* demo() {
int* arr = (int*)malloc(sizeof(arr) * N);
for(int i = 0; i < N; i++)
{
arr[i]=i;
}
return arr;
}
int main()
{
int* arr_p;
arr_p = demo();
printf("%d\n", *(arr_p+3));
free(arr_p);
return 0;
}
OUTPUT : 3
Had the similar situation when i have been trying to return char array from the function. But i always needed an array of a fixed size.
Solved this by declaring a struct with a fixed size char array in it and returning that struct from the function:
#include <time.h>
typedef struct TimeStamp
{
char Char[9];
} TimeStamp;
TimeStamp GetTimeStamp()
{
time_t CurrentCalendarTime;
time(&CurrentCalendarTime);
struct tm* LocalTime = localtime(&CurrentCalendarTime);
TimeStamp Time = { 0 };
strftime(Time.Char, 9, "%H:%M:%S", LocalTime);
return Time;
}

Dynamic String array dosent work

I'm trying to create a dynamic array of 1000 character long strings using calloc:
int i;
char** strarr =(char**)calloc(argc,sizeof(char)*1000);
if(strarr == NULL)
return 0;
strarr[0][0] ='a';
printf("%c\n",strarr[0][0]);
Every time i try to run this code i get segmentation fault on the printf line, i don't get why does this happen (you can assume that argc is bigger than 0)
Thanks
P.s. im sorry that the code is in text format but im using a mobile so i dont have the code feature
Try this:
const int num_of_strings = 255; //argc ?
const int num_of_chars = 1000;
int i;
char** strarr =(char**)malloc(sizeof(char*)*num_of_strings);
if(strarr == NULL)
return 0;
for (i = 0; i < num_of_strings; i++) strarr[i] = (char*)malloc(sizeof(char)*num_of_chars);
Hello and Welcome to the world of undefined behaviour, one of the darkest territories of the C language. Your code has several problems, which cause undefined behaviour in several occasions, but they all get executed, until you reach the printf line, where you are accessing memory, you have not allocated, which is finally caught by your system and, thus, a segmentation fault is produced.
But I think, it would be better to walk ourselves through your code.
The variable i, which is declared in the int i; line is not used anywhere in the code you have posted, but I guess you need it later.
The first piece of code, that is not right, is in this second line, where you declare an array of strings or a char**. That means that you have a pointer to pointers to chars. So, what you really want to do there is allocate memory for those pointers and not for the chars they will point to. Note that a char consumes a different amount of memory than a char*. This line is, thus, the one to go with.
char** strarr = (char**) calloc(argc, sizeof(char*));
This will allocate memory for argc blocks of memory, each of which is of size 4 or 8 bytes, which depends on whether your system is 32 or 64-bit.
You are doing a very good job of checking whether the calloc function returned NULL or not, which is a very good practice overall.
Next, you will want to allocate memory for the strings themselves, that are pointed to by the pointers, for which you allocated memory in the previous line. These lines will do it.
for (int i = 0; i < argc; i++) {
strarr[i] = (char*) calloc(1000, sizeof(char));
}
This will now allocate 1000-character lengthed strings for every element of our argc-sized string array.
After that, you can continue with your code as it is and I think that no errors will be produced. Please accept an additional piece of advice from me. Learn to love valgrind. It is a very helpful program, which you can run your code with, in order to analyse memory. It is my first step, whenever I get a segmentation fault.

How do you free a 2D malloc'd array in C?

I'm creating a 2D Array in C; am I freeing it correctly?
// create
int n = 3;
int (*X)[n] = malloc(sizeof(int[n][n]));
// set to 0
for(int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
X[i][j] = 0;
}
}
// is this all I need?
free(X);
You must call free once for each malloc. Your code has one malloc and one free (with the same address) so it is correct.
For every malloc(), there must be a matching free(). So if you call malloc() in a loop, there must be a similar loop later on that calls free() just as many times. Your code has one malloc() and one corresponding free(), so yes, you have freed everything you need to.
The most common way I've seen to allocate a two-dimensional array is to do something like:
int **arr = malloc(sizeof (int *) * num_rows);
for (i = 0; i < num_rows; ++i)
arr[i] = malloc(sizeof (int) * num_cols);
/*
* Using `sizeof *arr` and `sizeof **arr`
* respectively would have been more safe,
* but for the purpose of this example, I think
* using `int *` and `int` is simpler to
* understand.
*/
then later to free:
for (i = 0; i < num_rows; ++i)
free(arr[i]);
free(arr);
This makes the outer dimension hold num_row pointers to pointers to int (each of the num_row pointers points to the starting address of the 'column'). So each element in the outer dimension points to a row, and in each row there are num_cols elements in the inner dimension (the 'columns'), which is just a group of num_cols integers. Does this make sense to you? So you have to allocate num_rows integer pointers, and each one of these points to the first 'column' of that row--for each row you have to allocate space for num_cols integers, so you can see the loop will make a total of num_rows * num cols integers, and they way they are allocated allows you to use array indexing notation (two-dimensional in this case--each element in the outer dimension points to the start of a 'row', which contains a pointer to the start of a 'column', hence the double pointer) to access the elements. I know this is probably confusing, that is why I tried to describe it so many different times/ways, but please just ask any questions, especially about what you don't understand in particular, and I will be more than happy to work with you in helping understand it.
I'm not saying you have to create your 2-D array this way; your way works fine too, I just wanted to show you this way since you are likely to run into it since it's very common.
Also, look into Valgrind. You can use that tool to see if you have forgotten any free()s / have an unmatched malloc(), and lets you know if there is any allocated memory unreachable/leaked (maybe the pointer was changed before the call to free() so the call doesn't properly free the memory and you get a leak).
RastaJedi - another couple of things to note:
After a call to free(), it's a good idea to set the free'd variable to NULL, which helps prevent use after free.
Also, if you malloc in one block of code, then free in some called function, and then return from that function, sometimes C forgets about the final free (in your example, free(arr) ), and you should set the variable to NULL upon return.
I came here, and verified that the malloc and free calls that I wrote in the code I'm working on are indeed exactly as your "common" way, but kept running into a Seg Fault, because I was using malloc from in main, free-ing from a helper function which received the double-indirect head of the array. Having that all wrapped in a while-loop for user interaction, a second pass around was checking the array head for NULL-ness, but not seeing it as NULL, despite explicitly setting to NULL inside the helper function. Crawling thru the code with a debugger is how I identified the behavior, and why I came looking.
After being free'd, the memory is available, and variously (and randomly) reassigned; when the function with the free() calls returns, the memory that was allocated has been released, however it seems that the calling code still holds a pointer to that place in memory. There then exists a possible race-condition; by the time the calling code regains control, there's no guarantee as regards the location pointed to by the variable used for the array head, and therefore it's a very good idea to set the variable to NULL after the function returns.
Although you can use malloc'd pointers for pass-by-reference behavior, after a call to free() inside some function, the by-reference behavior breaks (because the thing being referenced is what has been free'd).
So, thank you for your answer, which confirmed that I was looking at the wrong part of my problem - just figured maybe someone else may stumble here, and possibly have the same issue I did.

malloc() causing crash with de-referenced 2-D character array in loop

Arrays is initialized as:
char** aldos = NULL;
char** aldoFilenames = NULL;
Function definition is:
int readFilesFromDirectory(char*** dest, char*** nameDest)
Passed to function via:
readFilesFromDirectory(&aldos, &aldoFilenames);
After counting the files, dest and nameDest are initialized:
*dest = (char**)malloc(sizeof(char*)*count);
*nameDest = (char**)malloc(sizeof(char*)*count);
count = 0; //resetting to read in the files again
First filename for nameDest is read in like:
*nameDest[count] = (char*) malloc(sizeof(char)*strlen(findData.cFileName) + 1);
strcpy(*nameDest[count], findData.cFileName);
//can confirm in my program, the value exists properly in *nameDest[count]
count++;
Heres where the problem comes in, when I throw it in a loop, it crashes (with no real useful error codes):
while (FindNextFile(hfind, &findData) != 0)
{
*nameDest[count] = (char*) malloc(sizeof(char)*strlen(findData.cFileName) + 1); //doesnt make it past here, CRASH
sprintf(*nameDest[count],"%s\0",findData.cFileName);
count++;
}
Any insight would be appreciated, I'll be quick to add more information if requested
In *nameDest[count], the indexing operator place before the dereference operator, making the code equivalent to *(nameDest[count]), which is not what you want since nameDest points to the array. You need to do the pointer dereference before the array indexing by using parenthesis: (*nameDest)[count]
I should also note that polling the OS twice for the directory listing - once for the count and once for the actual names - is unreliable, as between the two polls, the count might have changed. Consider using realloc to resize the array as you find more entries.
Several problems in the code
1) the expression: sizeof(char) is defined as 1 and multiplying anything by 1 has no effect, especially as part of a malloc() parameter, so it just clutters the code and accomplishes nothing.
Suggest removing the sizeof(char) expressions.
2) the memory allocation family (malloc, calloc, realloc) have a returned type of void* which can be assigned to any other pointer, so the cast is unneeded, just clutters the code and is a real headache when debugging and/or maintaining the code.
Suggest remove the casting of the returned values from malloc()
3) in C, array offsets start with 0 and end with array size -1 So when an array of size count is allocated, the valid offsets are 0...count-1.
However, the posted code is accessing array[count] which is past the end of the array, this is undefined behaviour and can/will lead to a seg fault event.

Free Dynamically Allocated Array C

I am in a bit of dilemma, thus, first of all I would like to apologize of if the next questions will be a bit more noobish or if they have been asked before (I couldn't find the answers for those though).
Anyway, I will explain it by giving a task as an example (it's not homework, it's just for the sake of my question). Here it goes:
Given a string from stdin index each word, then print each word on one line.
Example:
str[] = "Stack is awesome"
str_index {
[0] => "Stack"
[1] => "is"
[2] => "awesome"
}
I know that there are many ways to solve this, but, again, for the sake of my question
Bare this solution:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/* fgets adds an unwanted '\n' at the end, so I made
* a special function to read from stdin that removes
* that '\n'.
*/
int read(char *str, int size) {
// fgets adds an unwanted '\n' at the end, so we remove it
fgets(str, size, stdin);
int length = strlen(str);
str[length - 1] = '\0';
return length;
}
/* A function that breaks a string into words, indexes them
* and prints them out, all done dynamically with malloc.
*/
void str_index(char *str) {
char **index, *ptr;
int i = 0, number_of_words;
index = malloc(sizeof(char *));
ptr = strtok(str, " ");
for(i = 0; ptr != NULL; i++) {
index = realloc(index, (i + 1) * sizeof(char *));
index[i] = malloc(50 * sizeof(char));
strcpy(index[i], ptr);
ptr = strtok(NULL, " ");
}
number_of_words = i;
for(i = 0; i < number_of_words; i++) {
printf("%s\n", index[i]);
}
return;
}
int main() {
char str[250];
read(str, 250);
str_index(str);
return 0;
}
QUESTIONS
Where do I have to free the arrays that I have allocated dynamically
in str_index?
Do we have to free them within the function str_index? If so, why?
What I know is that when a function is done executing all local
variables are destroyed.
Why do we have to free them in main? Isn't main a function aswell,
thus upon finishing executing it all variables defined in that function are destroyed.
I'm guessing you are doing a university course. The problem (in my opinion) with university courses is that they start by teaching high level languages where everything is done magically, and then teach you a low level language. If I ruled the world, everyone would start with assembler, then C, then be allowed to 'progress' to Java etc.
To your question, the problem you have is the assumption that 'things might be done magically'. C doesn't do very much magically at all. In particular, if you malloc() or calloc() anything, or allocate anything using something that uses the heap allocator (for instance strdup()), it's your responsibility to free it. And you will need to do that explicitly. If you don't, you will have a memory leak. The first order problem is thus 'if I allocated it, I must ensure it is freed'. The second order problem is 'if I used a library that might have allocated stuff, I need to work out how to ensure it knows I've done, so it can free stuff'. If you bear this in mind, your C programming life will be happy, and valgrind will be your friend.
Let's now consider your questions:
You ask where you should free your dynamically allocated memory. Technically, in this example, you don't need to, because exiting your program will free all memory on the heap. However, let's suppose you want to use this function repeatedly. You want to free the allocation as soon as you no longer have a use for it. In the example presented, that would be immediately before the return. If you had other exits from the function, then make sure you free your allocation before every return. A useful error handling hint is to exit via the same code, and whenever you free() the allocation, also set the pointer to the allocation to NULL. On entry, also initialise the pointer to NULL. Then on exit (a valid use of goto), you can simply check the pointer against NULL, and if it is not null, free() it. (In fact once you get really cocky, you will know free() on NULL on most platforms is a no-op, so you can unconditionally free it). The setting the pointer to NULL bit is to avoid a double free.
This is the difference between the stack and the heap. Local variables are allocated on the stack. C destroys them automatically when a function returns. This is one of the few bits of magic C does. Note that I said it destroys the variables, not the things they point to. So if you have a pointer to allocated (heap) memory in a local variable, and the function returns, it will 'free' the variable (in the sense it will no longer be on the stack), but the allocated (heap) memory will not be freed. This is why you must free heap allocated memory only referenced in a function before the pointers to it are destroyed by exiting the function - see the answer to 1 above.
You don't need to free anything in main() in your example. If you had coded your function to return a pointer to memory on the heap (for instance if you'd coded the equivalent of strdup()) then your main() function would need to free() that. That brings up the important point that what the caller needs to free() depends on how the called function is designed. It's thus important that the called function makes this obvious in documentation.
Where do I have to free the arrays that I have allocated dynamically in str_index?
Just before the return; statement of your function str_index.
Do we have to free them within the function str_index?
Not necessary. Depends on the program requirement.
What I know is that when a function is done executing all local variables are destroyed.
Yes, it is true for space allocated on stack (if variable is not static), but not for the space allocated on heap.
Why do we have to free them in main?
Not necessary that it have to free in main. Depends on the program requirement.

Resources