For some reason, my function is only returning the first element in my array and I cannot figure out why the rest of the array goes out of scope. The function takes two integer arrays, adds their respective elements, and puts the sum into a third array which is returned.
Here is my code:
#include <stdio.h>
/* count digits, white space, others */
int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len);
void main() {
int arr1[10];
size_t arr1len = 10;
int arr2[10] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
size_t arr2len = 10;
int i;
int *x;
arr1[0] = 2;
arr1[1] = 3;
arr1[2] = 2;
arr1[3] = 2;
arr1[4] = 2;
arr1[5] = 2;
arr1[6] = 3;
arr1[7] = 2;
arr1[8] = 2;
arr1[9] = 2;
//printf("%d\t%d\t%d\n", arr1, *arr1, *(arr1 + 1));
x = sumarrays(arr1, arr1len, arr2, arr2len);
for (i = 0; i < 10; i++) {
printf("Array1: %d\tArray 2: %d\tX = %d\n", arr1[i], arr2[i], x[i]);
}
//return 0;
}
int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) {
int i;
int total[10];
for (i = 0; i < 10; i++) {
total[i] = *(arr1 + i) + *(arr2 + i);
}
for (i = 0; i < 10; i++) {
printf("%d\t", total[i]);
}
printf("\n");
return total;
}
Here is the output:
4 5 4 4 4 4 5 4 4 4
Array1: 2 Array 2: 2 X = 4
Array1: 3 Array 2: 2 X = 1974388256
Array1: 2 Array 2: 2 X = -161927102
Array1: 2 Array 2: 2 X = 2686628
Array1: 2 Array 2: 2 X = 8670801
Array1: 2 Array 2: 2 X = 0
Array1: 3 Array 2: 2 X = 27
Array1: 2 Array 2: 2 X = 2686540
Array1: 2 Array 2: 2 X = 4
Array1: 2 Array 2: 2 X = 2686916
The first line is the sum array elements from within the function. The remainder is what happens in the main().
What am I missing?
*edit* ANSWERED
Thank you everyone for the help! I actually learned C and C++ a while ago but have recently started to go back and fine tune my knowledge. Really appreciate all the help.
The main answers were
1) Statically allocate memory (using the static keyword)
2) Dynamically allocate memory (using malloc())
3) Make the variable global
4) Pass the result total() as an argument to the function so it doesn't go out of scope.
You are doing stack allocation for your array, and stack-allocated storage goes away when a function returns. Use heap allocation instead.
Change
int total[10];
to
int* total = malloc(10*sizeof(int)).
of course, that means you must also free the memory after you are done with it. In this case, before the return 0; in main, you need to
free(x);
my function is only returning the first element in my array and I cannot figure out why the rest of the array goes out of scope.
No, it returns a pointer to the first element - and the entire array goes out of scope. Any data you see that happens to remain as it was in the function is by luck rather than judgement, and you cannot use it as it is released for use by other functions.
Arrays are not first class data types in C - you cannot return an array by copy.
The normal solution is to have the array owned by the caller and to pass its address and size to the function.
int* func( int* arr, int arrlen )
{
// write to arr[0] to arr[arrlen-1] ;
return arr ;
}
int main()
{
int array[256] ;
func( array, sizeof(arr)/sizeof*(*arr) ) ;
}
Other less common and generally ill-advised possibilities are either to return a struct containing the array (a struct is a first class data type), but to do that is somewhat inefficient in many cases, or to dynamically allocate the array within the function, but it is not a particularly good idea since the caller has the responsibility of freeing that memory and may not be aware of that responsibility - it is a recipe for a memory leak.
The problem is that when sumarrays returns, the total array ceases to exist1, so the pointer value that main receives is no longer valid. In short, you cannot return arrays from a function like this.
You have several options.
The first (and IMO the preferred option) is to pass the total array as one of your parameters, and make the caller responsible for setting aside enough memory:
void sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len, int *total, size_t totallen)
{
...
for (i = 0; i < totalLen; i++) {
total[i] = *(arr1 + i) + *(arr2 + i);
...
}
#define ARRLEN 10
int main( void )
{
...
int x[ARRLEN];
...
sumarrays( arr1, ARRLEN, arr2, ARRLEN, x, ARRLEN);
In this method, the caller (main) is responsible for knowing how big the target array needs to be and setting aside the memory for it. The helps decouple the sumarrays function from main because it doesn't have to rely on information that isn't explicitly specified by the parameter list (such as the array sizes). With this approach, you're not limited to arrays of size 10.
A second option is to declare total such that it doesn't go away after sumarrays exits. You can do this by either declaring it at file scope (as in ryyker's answer), or by declaring it static within the sumarrays function:
int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) {
int i;
static int total[10];
...
With this approach, the total array will be allocated at program startup and held until the program terminates. What makes this approach less desireable is that you have only a single instance of that total array, which is shared across all calls to sumarrays. The function is no longer re-entrant; if sumarrays called another function that called sumarrays, then whatever the first call had written to total would be clobbered by the second call (the strtok library function has this problem, which has caused much heartburn in the past). Your code obviously doesn't have this problem, but it's something to be aware of. Don't declare things static if you don't have to.
The final option is for sumarrays to allocate the memory for total dynamically (as in haccks' and merlin2011's answers). That avoids the re-entrancy issue, but now you have to deal with memory management. C isn't your mother and won't clean up after you, so any memory you allocate with malloc or calloc you have to release with free2.
1. Logically speaking, anyway; the memory is obviously still there, but it's been made available for the rest of the system to use, and has been overwritten in the time it took for your program to return to the main function.
2. Most platforms will reclaim dynamically allocated memory when the program exits, but a few (admittedly older, oddball platforms) may not. Also, for long-running programs (servers, daemons, etc.), you have to be very careful to release any memory you allocated and no longer need, otherwise you will eventually run out.
You can't return a pointer to an automatic local variable. total is an automatic local variable and it doesn't exist after function body executed.
Pointer to static local variable or dynamically allocated variable can be returned. Change
int total[10]; to
int *total = malloc(10 * sizeof(int));
I agree with every other answer regarding automatic (stack) and heap memory. All good approaches, however global variables on the stack are also an option. It is important to note that it was not that you chose to use stack memory, but that it was also local in scope. Locally scoped automatic variables die when the function that created them returns. However, globally scoped variables, also stored using stack memory, live for the duration of your program, and therefore provide an alternative approach to solve your problem...
A one line change will result in your code running, change your local copy of total (automatic scope) to a global:
int total[10];//Put this here, outside of any function block in same file, i.e. (will give it global scope)
//note, commented this in function below
int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) {
int i;
//int total[10];//move this to global scope
for (i = 0; i < 10; i++) {
total[i] = *(arr1 + i) + *(arr2 + i);
}
for (i = 0; i < 10; i++) {
printf("%d\t", total[i]);
}
printf("\n");
return total;
}
With this approach, global scope of variable allows your return to be successful. The array total keeps it's existence on stack until program exits.
Related
im new to the C language and im trying to understand the basic of memory allocation .
here I have two function that produce the exact same result, but only one of them using the malloc() function and the other one is not.
FIRST FUNCTION
int First()
{
int arr[] = {11, 13, 7, 12, 16};
int length = sizeof(arr) / sizeof(int);
// NOT using malloc
int arr2[length];
// Initialize elements to 0
for (int i=0; i < length; i++)
arr2[i] = 0;
// Print results
for (int i = 0; i < length; i++)
printf("%d ", arr2[i]);
return 0;
}
SECOND FUNCTION
int Second()
{
int arr[] = {11, 13, 7, 12, 16};
int length = sizeof(arr) / sizeof(int);
int *arr2;
// Here im using malloc to allocate memory
arr2 = malloc(sizeof *arr2 * length);
// Initialize elements to 0
for (int i=0; i < length; i++)
arr2[i] = 0;
// Print results
for (int i = 0; i < length; i++)
printf("%d ", arr2[i]);
return 1;
}
Both of this two functions will print: 0 0 0 0 0.
What are the differences between this two approaches ? I know that using malloc(or memset) to allocate memory based on a variable is the right approach , but im trying to understand why exactly ?
Thanks!
The difference is the lifetime of the objects. Basically it means when the object is valid and it can be accessed.
Generally, there are three lifetime types:
Static
The object is valid all the time
Example:
int* foo(void) {
static int A[10];
return A;
}
Array A is always valid. It can be safely returned from a function.
Automatic
The object is valid from its definition to end of the block where it was declared
Example:
void foo(void) {
int *p;
{
int A[10];
... A is valid here ...
p = &A[0]; // p points to
*p = 42; // still valid
}
// A is no longer valid
*p = 666; // UB strikes, expect everything
}
A pointers to automatic objects should never be returned from functions because they would point to non-existing objects. Any use of value of such a pointer triggers Undefined behavior.
Dynamic
The lifetime is controlled by the program. It starts with memory allocation via malloc() or similar functions. It ends when calling free() on the pointer to this object. Dynamic object can only be accessed via a pointer.
Example:
int* foo(void) {
int *p;
{
p = malloc(sizeof(int[10])); // p points to an object for 10 ints
*p = 42; // still valid
}
*p = 43; // still valid
return p; // still valid though function has returned
}
int *p = foo();
*p = 44;
free(p); // release
*p = 666; // UB strikes, expect everything
Forgetting to call free() usually leads to the memory leak.
The second function has a memory leak because the dynamically allocated array was not freed.
The first function is conditionally supported by compilers due to using a variable length array. Also if the size of the array is big then it can occur such a way that the array will not be allocated.
And the function memset allocates nothing.
One of the differences that I can come up with is the sizes of the arrays.
In your first function, if you put sizeof(arr2) at the end, you will get 20. But at your second function, when you put sizeof(arr2) you will get 8. (Size of a pointer depends on your computer. A pointer's size is 8 bytes in 64-bit mode. And 4 bytes in 32-bit mode.)
I wanted to create a function that deletes from an array of segments the ones that are longer than a given number, by freeing the memory I don't need anymore. The problem is that the function I've created frees also all the memory allocated after the given point. How can I limit it, so that it frees just one pointer without compromising the others?
Here is the code I've written so far:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
typedef struct
{
double x1;
double y1;
double x2;
double y2;
} Segment;
double length(Segment* s)
{
return sqrt(pow(s->x1 - s->x2, 2) + pow(s->y1 - s->y2, 2));
}
// HERE IS THE PROBLEM!!
void delete_longer(Segment* as[], int n, double max_len)
{
for(int i = 0; i < n; i++)
{
if(length(as[i]) > max_len)
{
as[i] = NULL; // Those two lines should be swapped, but the problem remains
free(as[i]);
}
}
}
int main()
{
const int SIZE = 5;
Segment** arr = (Segment**)calloc(SIZE, sizeof(Segment*));
for(int i = 0; i < SIZE; i++)
{
arr[i] = (Segment*)malloc(sizeof(Segment));
}
srand(time(0));
for(int i = 0; i < SIZE; i++)
{
arr[i]->x1 = rand() % 100;
arr[i]->x2 = rand() % 100;
arr[i]->y1 = rand() % 100;
arr[i]->y2 = rand() % 100;
printf("Lungezza: %d\n", (int)length(arr[i]));
}
delete_longer(arr, SIZE, 80);
for(int i = 0; i < SIZE && arr[i]; i++)
{
printf("Lunghezza 2: %d\n", (int)length(arr[i]));
}
return 0;
}
First of all the free function should come after the instruction that sets the pointer to NULL, but that's not the main cause of the problem.
What causes the behaviour I described was the fact that the second for loop in the main stops after finding the first NULL pointer. Instead I should have written:
for(int i = 0; i < SIZE ; i++)
{
if(arr[i])
printf("Lunghezza 2: %d\n", (int)length(arr[i]));
}
You have two main problems:
In the delete function you write:
as[i] = NULL;
free(as[i]);
This is the wrong order. You must first free the memory and then set the element to null. But note that this is not the cause of your perceived problem, it only causes a memory leak (i.e. the memory of as[i] becomes inaccessible). You should write:
free(as[i]);
as[i] = NULL;
Your second problem is in your for loop, which now stops at the first null element. So not all the memory after it is deleted, you just don't print it. The loop should be for example:
for(int i = 0; i < SIZE; i++)
{
printf("Lunghezza 2: %d\n", arr[i]?(int)length(arr[i]):0);
}
Note: I agree with the discussion that free(NULL) may be implementation dependent in older implementations of the library function. In my personal opinion, never pass free a null pointer. I consider it bad practice.
There's no way to change the size of an array at runtime. The compiler assigns the memory statically, and even automatic arrays are fixed size (except if you use the last C standard, in which you can specify a different size at declaration time, but even in that case, the array size stands until the array gets out of scope). The reason is that, once allocated, the memory of an array gets surrounded of other declarations that, being fixed, make it difficult ot use the memory otherwise.
The other alternative is to allocate the array dynamically. You allocate a fixed number of cells, and store with the array, not only it's size, but also its capacity (the maximum amount of cell it is allow to grow) Think that erasing an element of an array requires moving all the elements behind to the front one place, and this is in general an expensive thing to do. If your array is filled with references to other objects, a common technique is to use NULL pointers on array cells that are unused, or to shift all the elements one place to the beginning.
Despite the technique you use, arrays are a very efficient way to access multiple objects of the same type, but they are difficult to shorten or enlengthen.
Finally, a common technique to handle arrays in a way you can consider them as variable length is to allocate a fixed amount of cells (initially) and if you need more memory to allocate double the space of the original (there are other approaches, like using a fibonacci sequence to grow the array) and use the size of the array and the actual capacity of it. Only in case your array is full, you call a function that will allocate a new array of larger size, adjust the capacity, copy the elements to the new copy, and deallocate the old array. This will work until you fill it again.
You don't post any code, so I shall do the same. If you have some issue with some precise code, don't hesitate to post it in your question, I'll try to provide you with a working solution.
So, I have this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void remove_element(int* array, int sizeOfArray, int indexToRemove)
{
int* temp = malloc((sizeOfArray - 1) * sizeof(int*)); // allocate an array with a size 1 less than the current one
memcpy(temp, array, indexToRemove - 1); // copy everything BEFORE the index
memcpy(temp+(indexToRemove * sizeof(int*)), temp+((indexToRemove+1) * sizeof(int*)), sizeOfArray - indexToRemove); // copy everything AFTER the index
free (array);
array = temp;
}
int main()
{
int howMany = 20;
int* test = malloc(howMany * sizeof(int*));
for (int i = 0; i < howMany; ++i)
(test[i]) = i;
printf("%d\n", test[16]);
remove_element(test, howMany, 16);
--howMany;
printf("%d\n", test[16]);
return 0;
}
It's reasonably self-explanatory, remove_element removes a given element of a dynamic array.
As you can see, each element of test is initialised to an incrementing integer (that is, test[n] == n). However, the program outputs
16
16
.
Having removed an element of test, one would expect a call to to test[n] where n >= the removed element would result in what test[n+1] would have been before the removal. So I would expect the output
16
17
. What's going wrong?
EDIT: The problem has now been solved. Here's the fixed code (with crude debug printfs), should anyone else find it useful:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int remove_element(int** array, int sizeOfArray, int indexToRemove)
{
printf("Beginning processing. Array is currently: ");
for (int i = 0; i < sizeOfArray; ++i)
printf("%d ", (*array)[i]);
printf("\n");
int* temp = malloc((sizeOfArray - 1) * sizeof(int)); // allocate an array with a size 1 less than the current one
memmove(
temp,
*array,
(indexToRemove+1)*sizeof(int)); // copy everything BEFORE the index
memmove(
temp+indexToRemove,
(*array)+(indexToRemove+1),
(sizeOfArray - indexToRemove)*sizeof(int)); // copy everything AFTER the index
printf("Processing done. Array is currently: ");
for (int i = 0; i < sizeOfArray - 1; ++i)
printf("%d ", (temp)[i]);
printf("\n");
free (*array);
*array = temp;
return 0;
}
int main()
{
int howMany = 20;
int* test = malloc(howMany * sizeof(int*));
for (int i = 0; i < howMany; ++i)
(test[i]) = i;
printf("%d\n", test[16]);
remove_element(&test, howMany, 14);
--howMany;
printf("%d\n", test[16]);
return 0;
}
I see several issues in the posted code, each of which could cause problems:
returning the new array
Your function is taking an int* array but then you are trying to swap it with your temp variable at the end prior to returning the new array. This will not work, as you are simply replacing the local copy of int* array which will disappear after you return from the function.
You either need to pass your array pointer in as an int**, which would allow you to set the actual pointer to the array in the function, or, I would suggest just returning a value
of int* for your function, and returning the new array.
Also, as mentioned in this answer, you really don't even need to reallocate when deleting an element from the array, since the original array is big enough to hold everything.
size and offset calculations
You are using sizeof(int*) for calculating the array element size. This may work for some types, but, for instance, for a short array sizeof(short*) does not work. You don't want the size of the pointer to the array, you want the size of the elements, which for your example should be sizeof(int) although it may not cause problems in this case.
Your length calculation for the offsets into the arrays looks ok, but you're forgetting to multiply the number of elements by the element size for the size parameter of the memcpy. e.g. memcpy(temp, array, indexToRemove * sizeof(int));.
Your second call to memcpy is using temp plus the offset as the source array, but it should be array plus the offset.
Your second call to memcpy is using sizeOfArray - indexToRemove for the number of elements to copy, but you should only copy SizeOfArray - indexToRemove - 1 elements (or (sizeOfArray - indexToRemove - 1) * sizeof(int) bytes
Wherever you are calculating offsets into the temp and array arrays, you don't need to multiply by sizeof(int), since pointer arithmetic already takes into account the size of the elements. (I missed this at first, thanks to: this answer.)
looking at incorrect element
You are printing test[16] (the 17th element) for testing, but you are removing the 16th element, which would be test[15].
corner cases
Also (thanks to this answer) you should handle the cases where indexToRemove == 0 and indexToRemove == (sizeOfArray - 1), where you can do the entire removal in one memcpy.
Also, you need to worry about the case where sizeOfArray == 1. In that case perhaps either allocate a 0 size block of memory, or return null. In my updated code, I chose to allocate a 0-size block, just to differentiate between an array with 0 elements vs. an unallocated array.
Returning a 0-size array also means there are no additional changes necessary to the code, because the conditions before each memcpy to handle the first two cases mentioned will prevent either memcpy from taking place.
And just to mention, there's no error handling in the code, so there are implicit preconditions that indexToRemove is in bounds, that array is not null, and that array has the size passed as sizeOfArray.
example updated code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int* remove_element(int* array, int sizeOfArray, int indexToRemove)
{
int* temp = malloc((sizeOfArray - 1) * sizeof(int)); // allocate an array with a size 1 less than the current one
if (indexToRemove != 0)
memcpy(temp, array, indexToRemove * sizeof(int)); // copy everything BEFORE the index
if (indexToRemove != (sizeOfArray - 1))
memcpy(temp+indexToRemove, array+indexToRemove+1, (sizeOfArray - indexToRemove - 1) * sizeof(int)); // copy everything AFTER the index
free (array);
return temp;
}
int main()
{
int howMany = 20;
int* test = malloc(howMany * sizeof(int));
for (int i = 0; i < howMany; ++i)
test[i] = i;
printf("%d\n", test[16]);
test = remove_element(test, howMany, 16);
--howMany;
printf("%d\n", test[16]);
free(test);
return 0;
}
a few words on memory management/abstract data types
Finally, something to consider: there are possible issues both with using malloc to return memory to a user that is expected to be freed by the user, and with freeing memory that a user malloced. In general, it's less likely that memory management will be confusing and hard to handle if you design your code units such that memory allocation is handled within a single logical code unit.
For instance, you might create an abstract data type module that allowed you to create an integer array using a struct that holds a pointer and a length, and then all manipulation of that data goes through functions taking the structure as a first parameter. This also allows you, except within that module, to avoid having to do calculations like elemNumber * sizeof(elemType). Something like this:
struct MyIntArray
{
int* ArrHead;
int ElementSize;
// if you wanted support for resizing without reallocating you might also
// have your Create function take an initialBufferSize, and:
// int BufferSize;
};
void MyIntArray_Create(struct MyIntArray* This, int numElems /*, int initBuffSize */);
void MyIntArray_Destroy(struct MyIntArray* This);
bool MyIntArray_RemoveElement(struct MyIntArray* This, int index);
bool MyIntArray_InsertElement(string MyIntArray* THis, int index, int Value);
etc.
This is a basically implementing some C++-like functionality in C, and it's IMO a very good idea, especially if you are starting from scratch and you want to create anything more than a very simple application. I know of some C developers that really don't like this idiom, but it has worked well for me.
The nice thing about this way of implementing things is that anything in your code that was using the function to remove an element would not ever be touching the pointer directly. This would allow several different parts of your code to store a pointer to your abstract array structure, and when the pointer to the actual data of the array was reallocated after the element was removed, all variables pointing to your abstract array would be automatically updated.
In general, memory management can be very confusing, and this is one strategy that can make it less so. Just a thought.
You don't actually change the passed pointer. You're only changing your copy of array.
void remove_element(int* array, int sizeOfArray, int indexToRemove)
{
int* temp = malloc((sizeOfArray - 1) * sizeof(int*));
free (array); /* Destroys the array the caller gave you. */
array = temp; /* Temp is lost. This has **no effect** for the caller. */
}
So after the function the array still points to where it used to point BUT, you've also freed it, which adds insult to injury.
Try something like this:
void remove_element(int **array, int sizeOfArray, int indexToRemove)
^^
{
int *temp = malloc((sizeOfArray - 1) * sizeof(int*));
/* More stuff. */
free(*array);
*array = temp;
}
There is also a C FAQ: Change passed pointer.
#cnicutar is right (+1), but also, you write:
memcpy(temp+(indexToRemove * sizeof(int*)), temp+((indexToRemove+1) * sizeof(int*)), sizeOfArray - indexToRemove); // copy everything AFTER the index
while it should be:
memmove(temp+(indexToRemove), temp+(indexToRemove+1), sizeOfArray - indexToRemove); // copy everything AFTER the index
Since the multiplication by the size of int* is done by the compiler (that's pointer arithmetic)
Also, when moving overlaying memory areas, use memmove and not memcpy.
Further: the second argument to your second memcpy call should be based on array, not on temp, right? And shouldn't you be mallocing and copying based on sizeof int and not based on sizeof int*, since your arrays store integers and not pointers? And don't you need to multiply the number of bytes you're copying (the last argument to memcpy) by sizeof int as well?
Also, watch the case where indexToRemove == 0.
There are a few problems with that code :
(a) When allocating memory, you need to make sure to use the correct type with sizeof. For an array of int eg., you allocate a memory block with a size that is a multiple of sizeof(int). So :
int* test = malloc(howMany * sizeof(int*));
should be :
int* test = malloc(howMany * sizeof(int));
(b) You don't free the memory for the array at the end of main.
(c) memcpy takes the amount of bytes to copy as the third parameter. So, you need to again make sure to pass a multiple of sizeof(int). So :
memcpy(temp, array, cnt);
should be :
memcpy(temp, array, cnt * sizeof(int));
(d) when copying items from the old array to the new array, make sure to copy the correct data. For example, there are indexToRemove items before the item at index indexToRemove, not one less. Similarly, you'll need to make sure that you copy the correct amount of items after the item that needs to be removed.
(e) When incrementing a pointer, you don't need to multiply with sizeof(int) - that's done implicitly for you. So :
temp + (cnt * sizeof(int))
should really be :
temp + cnt
(f) In your remove_element function, you assign a value to the local variable array. Any changes to local variables are not visible outside of the function. So, after the call to remove_element ends, you won't see the change in main. One way to solve this, is to return the new pointer from the function, and assign it in main :
test = remove_element(test, howMany, 16);
All the other answers make good points about the various problems/bugs in the code.
But, why reallocate at all (not that the bugs are all related to reallocation)? The 'smaller' array will fit fine in the existing block of memory:
// Note: untested (not even compiled) code; it also doesn't do any
// checks for overflow, parameter validation, etc.
int remove_element(int* array, int sizeOfArray, int indexToRemove)
{
// assuming that sizeOfArray is the count of valid elements in the array
int elements_to_move = sizeOfArray - indexToRemove - 1;
memmove( &array[indexToRemove], &array[indexToRemove+1], elements_to_move * sizeof(array[0]));
// let the caller know how many elements remain in the array
// of course, they could figure this out themselves...
return sizeOfArray - 1;
}
I have written a function that allocates and initialises a 2D array, like this -
static state **symbols;
void initNFAStates()
{
int i,j;
numStates = 256;
symbols = (state**)malloc(numStates * sizeof(char));
for(i = 0;i < numStates;i++)
{
symbols[i] = (state*)malloc(NUMSYMBOLS * sizeof(state));
for(j = 0;j < NUMSYMBOLS;j++)
symbols[i][j] = 0;
}
}
and a function to print this array, like this -
void printNFAStateTable()
{
int i, j;
for(i = 0;i < numStates;i++)
{
printf("%d \t",i);
for(j = 0;j < NUMSYMBOLS;j++)
printf("%ld",symbols[i][j]);
printf("\n");
}
}
When called consecutively from the main() function, they both work fine. However, the code as follows results in a segfault after reading only the first 32 lines from the array.
int main(int argc, char **argv)
{
int i;
clock_t begin, end;
double timeTaken;
currNFAState = 0;
initNFAStates();
if(getChars(argc,argv) != NULL)
{
printNFAStateTable();
begin = clock();
regex();
...
Similarly, the printf() function causes the same issue, but only when printing a floating point number -
int main(int argc, char **argv)
{
int i;
clock_t begin, end;
double timeTaken;
currNFAState = 0;
initNFAStates();
printf("A floating point number - %f",0.0124f);
printNFAStateTable();
...
I am aware this has to do with the symbols array being static, as the issue does not appear when the array is global. Could anyone explain why this occurs?
Given this declaration:
static state **symbols;
This allocation is incorrect:
symbols = (state**)malloc(numStates * sizeof(char));
The type of *symbols is state *; this is the type of the elements of the array you are dynamically allocating, and I feel confident in asserting that pointers on your machine are larger than char is. This would be a more appropriate allocation:
symbols = malloc(numStates * sizeof(*symbols));
(Note that you do not need to cast the return value of malloc(), and there are good reasons not to do so.)
Having not allocated memory sufficient for all the pointers you want to use, your program exhibits undefined behavior when it tries to access elements at indices that would fall outside the bounds of the allocation. That UB very easily could manifest in the form of library functions modifying memory you did not expect them to modify.
This is not doing what you expect:
symbols[i][j] = 0;
The reason is that this assumes a singularly allocated block of memory organized as a 2D array. That's not what you've created.
Your code indicates the first dimension is sized at 256, which would look like this:
state symbols[256][NUMSYMBOLS];
If you allocated globally or on the stack. This would be a single block of RAM sized as 256 * NUMSYBOLS * sizeof( state ), where each row is advanced NUMSYMBOLS * sizeof( state ).
What you're doing, however, is create an a array of pointers in one block of RAM, and then allocating additional blocks of RAM for each row. They are unrelated such that access is not going to work using the 2D array syntax.
What you need is first to access the pointer to the row, conceptually:
state *state_row = symbols[ i ];
This gives you the row. Now, get the column;
stat * state_cell = state_row[ j ];
This is expanded to show how to think about it, you can easily choose other specific means of accessing the appropriate cells.
I want to use only studio.h library to convert from decimal number to binary number by using an array to store remainder but the result is not correct, maybe i have problem with memory allocation or return value is wrong, please help me to check it.
Thank you so much!
#include <stdio.h>
int n = 0;
int* DecimalToBinary(int number){
int a[10];
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
void main(){
int *d1 = DecimalToBinary(5);
int *d2 = DecimalToBinary(10);
for(int i = n-1 ;i>=0;i--)
printf(" %d",d1[i]);
printf("\n");
for(int i = n-1 ;i>=0;i--)
printf(" %d",d2[i]);
}
You return a pointer to a local array. That local array is on the stack, and when the function returns the array goes out of scope and that stack memory will be reused when you call the next function. This means that the pointer will now point to some other data, and not the original array.
There are two solutions to this:
Declare the array in the function calling DecimalToBinary and pass it as an argument.
Create the array dynamically on the heap (e.g. with malloc) and return that pointer.
The problem with method 2 is that it might create a memory leak if you don't free the returned pointer.
As noted by Craig there is a third solution, to make the array static inside the function. However in this case it brings other and bigger problems than the two solutions I originally listed, and that's why I didn't list it.
There is also another serious problem with the code, as noted by Uchia Itachi, and that is that the array is indexed by a global variable. If the DecimalToBinary function is called with a too big number, or to many times, this global index variable will be to big for the array and will be out of bounds for the array.
Both the problem with dereferencing a pointer to an out-of-scope array and the indexing out of bounds leads to undefined behavior. Undefined behavior will, if you're lucky, just lead to the wrong result being printed. If you're unlucky it will cause the program to crash.
You are returning a pointer to a locally allocated array. It is allocated on the stack, and goes away when the function returns, leaving your pointer pointing to garbage.
You have a few options. You could pass an array in to fill:
void DecimalToBinary(int result[10],int number){
while(number!=0){
result[n++] = number%2;
number/=2;
}
return result;
}
// usage example:
int b[10];
DecimalToBinary(b, 42);
Or you could allocate an array on the heap:
int* DecimalToBinary(int number){
int *a = (int *)malloc(sizeof(int) * 10);
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
// usage example
int *b = DecimalToBinary(42);
free(b); // when finished with it
Or you could wrap the array in a struct:
typedef struct {
int b[10];
} result;
result DecimalToBinary(int number){
result r;
while(number!=0){
r.b[n++] = number%2;
number/=2;
}
return r;
}
// usage example
result r = DecimalToBinary(42);
If you do the malloc() option, do not forget to free() the returned data when you're done with it, otherwise it will hang around. This is called a memory leak. In more complex programs, it can lead to serious issues.
Note: By the way, if your number is larger than 1023 (10 binary digits), you'll overrun the array. You may also wish to explicitly stop once you've stored 10 digits, or pass the size of the array in, or compute the required size first and allocate that much space. Also, you will get some odd results if your number is negative, you might want to use number&1 instead of number%2.
Note 2: As noted elsewhere, you should make n local, or at the very least reinitalize it to 0 each time the function is called, otherwise it will just accumulate and eventually you'll go past the end of the array.
int[10] is not the same as int *; not only is the former created on the stack, it is a different type alltogether. You need to create an actual int * like so:
int *a = malloc (10 * sizeof (int));
Of course, don't forget to free() it after use!
What you can also do and what is commonly done in C is creating the array where it is called and provide a pointer to that array to the function, this way when the array is on the stack of the function that calls it and not in the function self. We also have to specify the size of the array on to that function, since the function cannot know to how many elements the pointer points to
void DecimalToBinary( int number, int* output, unsigned size ) {
/*adapt this to your liking*/
int i;
for ( i = 0; i < size && number != 0; i++) {
output[i] = number%2;
number/2;
}
}
and in you main function you would call it like this:
int array[10];
DecimalToBinary( 5, array, sizeof(array)/sizeof(array[0]));
now array has the same result as a would have had in your example.
The problem in your code lies here..
int * DecimalToBinary(int number){
int a[10];
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
The array a scope is only till this function. Once this function terminates, the memory allocated for this array will be released, either u need to use dynamic memory allocation or make array a global.
This is the correct program:
#include <stdio.h>
int n = 0;
int a[10] = {0};
int* DecimalToBinary(int number){
n = 0;
while(number!=0){
a[n++] = number%2;
number = number/2;
}
return a;
}
int main(){
int *d1;
int *d2;
int i;
d1 = DecimalToBinary(5);
for(i = n-1;i>=0;i--)
printf(" %d",d1[i]);
printf("\n");
d2 = DecimalToBinary(10);
for(i = n-1;i>=0;i--)
printf(" %d",d2[i]);
printf("\n");
}