C: Free temporary array produced by malloc-function - c

I have a c function that produces my a int array using malloc. It works quiet well and I think it isn't really important what it does because the problem doesn't really have anything to do with that. (In this case it calculates the numbers to a given int and base). I need this array temporary in a function, which might be a sub function of a sub function of a ... (you got the idea, point this function can be used several times) and before the return I would like to run free, but it doesn't work. Here is a testing code (it sorts an array of ints to the amount of ones in their binary representation using qsort (yes I know could have calculated the results more directly, but the point is the probleme I run into when trying to run free (here comment out in function ones))):
#include <stdio.h>
#include <stdlib.h>
int values[] = { 88, 56, 100, 2, 25, 0, 15};
int * baseString(int u, int base);
int abs(int a);
int ones(int a);
int cmpfunc (const void * a, const void * b)
{
return ones(*(int*)a)>ones(*(int*)b);
}
int main()
{
int n;
printf("Before sorting the list is: \n");
for( n = 0 ; n < 7; n++ )
{
printf("%d ", values[n]);
}
qsort(values, 7, sizeof(int), cmpfunc);
printf("\nAfter sorting the list is: \n");
for( n = 0 ; n < 7; n++ )
{
printf("%d (Ones=%d) ", values[n], ones(values[n]));
}
printf("\n");
return(0);
}
int abs(int a){
return (a<0)? a*-1:a;
}
int* baseString(int u, int base){
int* r=malloc(sizeof(int));
r[0]=base;
r[1]=1;
if(base<2){
r[2]=-1;
return r;
}
int negativ=0;
if(u<0){
u=abs(u);
negativ=1;
}
int i=2;
do{
int ur=u%base;
r[i]=ur;
u/=base;
i++;
}while(u>0);
r[1]=i-1;
if(negativ){
r[1]=-r[1];
}
return r;
}
int ones(int a){
int* ai=baseString(a, 2);
int a1=1;
for(int i=2; i<abs(ai[1]); i++){
if(ai[i]==1){
a1++;
}
}
if(!a){
a1=0;
}
//free(ai);
return a1;
}
PS: I am quiet sure this thread is duplicate of some tread somewhere, but I didn't found it.

Part of your problem is actually quite simple.
In your baseString() function, the first three lines are
int* r=malloc(sizeof(int));
r[0]=base;
r[1]=1;
The malloc() dynamically allocates a single int, or an array with one element. The r[1] = 1 modifies the second element of that array which has one element.
The result of that is undefined behaviour. A common symptom of running off the end of an array like this is corrupting memory in your program, such as that used internally by malloc() and free() to keep track of allocated and released memory. Which would explain your problem.
Make sure you allocate the number of elements needed. For example, if 10 elements are needed, malloc(10*sizeof(int)). You need to work out the number needed, since dynamically arrays will not magically grow to get the number of elements needed.
I haven't look further, so there may be other problems. But this one is pretty glaring.
It is also a good idea to check that malloc() actually succeeds. It returns NULL if it fails.

The key problem here appears to an ABW (Array Bounds Write). In the baseString function, you are actually allocating memory which is equivalent to the size of 1 integer, but are trying to access it like an array in r[1],r[2], r[i] etc, which results in write to memory which technically doesn't belong to you.
The code snippet in your code corresponds to
int* r=malloc(sizeof(int));
r[0]=base;
r[1]=1; //ABW here
if(base<2){
r[2]=-1; //ABW here
return r;
}
do{
int ur=u%base;
r[i]=ur; //ABW here
u/=base;
i++;
}while(u>0);
This might lead to undefined behavior at any point of time in your code. In your case, it seems to be affecting free as the memory overwrite may have messed up with the internal book keeping data of malloc and free implementation.

Related

malloc and pointer questions

We were shown this program in class yesterday and i have a question regarding it's output.
malloc.c:
#include <stdlib.h>
int *create_array(int);
int *create_array(int elements) {
int i,*x = (int *) malloc(elements*sizeof(int));
for(i=0;i < elements;i++) {
x[i] = i;
}
free(x);
return x;
}
int main(void) {
int j, *arr;
arr = create_array(5);
for(j=0;j<5;j++) {
printf("%d\n",arr[j]);
}
return 0;
}
Question(s):
When i run the program, i get this as output:
1627793032
1627793104
2
3
4
However, shouldn't the first 2 elements be 0 and 1 respectively? The values printed here seem like memory addresses to me, am i right? Also, is this due to some mistake causing undefined behavior?
After free(x);, the values pointed to by x are no longer valid. The memory can be reused for some other purpose, and meanwhile the memory allocation library can use the storage as it sees fit.
So, yes, it is a mistake resulting in undefined behaviour.
The real question is why do you even expect it to work? You free x, then you return a freed pointer which is nonsense.
What is happening is the following:
Inside the function you allocate 5 spaces, x points to the first
one's address.
You write 0, 1, 2, 3, 4 in these spaces.
You free x, so all the 5 spaces are not reserved anymore.
You exit the function, doing so the 2 next free memory spaces are
used, which happen to be the ones where you wrote 0 and 1.
You print the values contained in the 5 memory areas you've already
freed, where the ones in which you wrote 0 and 1 happen to have been
reused for something else; hence the weird numbers.
As a general rule, do not attempt to read areas of memory i've freed; even worse, do not try to WRITE there.
Accessing unallocated memory leads to undefined behaviour.
Also, you don't need to declare the function in a separate row if it's going to have nothing in between; plus you don't have to cast what's returned by malloc to the type; it's a void* that by default can hold anything you throw at it. What matters is your base variable type. See here
Corrected code:
#include <stdlib.h>
int *create_array(int elements) {
int i,*x = malloc(elements*sizeof(int));
for(i=0;i < elements;i++) {
x[i] = i;
}
return x;
}
int main(void) {
int j, *arr;
arr = create_array(5);
for(j=0;j<5;j++) {
printf("%d\n",arr[j]);
}
free(arr);
return 0;
}

Unable to understand the code

I was trying to make a code to find duplicates in an array and print them. I can't understand this code and why the Calloc is being used and the int main part isn't clear to me.
#include<stdio.h>
#include<stdlib.h>
void printRepeating(int arr[], int size)
{
int *count = (int *)calloc(sizeof(int), (size - 2));
int i;
printf(" Repeating elements are ");
for(i = 0; i < size; i++)
{
if(count[arr[i]] == 1)
printf(" %d ", arr[i]);
else
count[arr[i]]++;
}
}
int main()
{
int arr[] = {4, 2, 4, 5, 2, 3, 1};
int arr_size = sizeof(arr)/sizeof(arr[0]);
printRepeating(arr, arr_size);
getchar();
return 0;
}
The code is actually "dangerous", as it relies on some conditions to hold, e.g. that the maximum integer value in the array is not larger than size-2. So, if your input were, for example, int arr[] = { 114, 112, 114, 5, 2, 3, 1}, then arr[0] would be 114, and the code count[arr[0]]++ would exceed the bounds of the array allocated in printRepeating, which were just 5 elements.
I'd throw the code away and write your own; almost regardless on your experience, your code is likely not worse than the proposed one :-)
The reason for using calloc is that the size isn't known in advance. An alternative would be to use VLA but apparently the author preferred dynamic memory allocation. Kind of bad as the author forgot to free the memory. So this code leaks memory.
Besides that the code is very error prone as it relies on some specific rules for the input (e.g. that no input value is greater that size-2). So my advice is to through this code away and start all over.
BTW: The code uses calloc instead of malloc to get the memory zero initialized.
Regarding main.... This line:
int arr_size = sizeof(arr)/sizeof(arr[0]);
calculates the number of elements in the array.
sizeof(arr) is likely to return 28
sizeof(arr[0]) is likely to return 4
So
28/4 = 7 which is the number of array elements.
This code is really wrong, you shouldn't use it at all.
To give you some hints, this line creates an array:
int *count = (int *)calloc(sizeof(int), (size - 2));
Similar to:
int count[size - 2] // If size was a constant
An unfortunate issue is that the function never disposes the dynamically created array, so you'll see a memory leak.
Line count[arr[i]]++ is a disaster: if the value of arr[i] is greater than size-2 then the software will write to an unassigned memory.
To show how it should be done:
// No value should exceed 50
#define MAX_ARR 50
void printRepeating(int arr[], int size)
{
int found[MAX_ARR];
int i;
// Set found variable to 0
memset(found, 0, sizeof(found));
for(i = 0; i < size; i++)
{
// Did we find the same number before?
if (found[arr[i]] == 1) {
// Yes, print it
printf(" %d ", arr[i]);
} else {
// No, mark is as found
found[arr[i]] = 1;
}
}
}
Actually we use malloc( ) for allocating a single block of specified size that returns a pointer of type of void. This means that we can assign it to any type of type. Form is:
ptr = ( cast - type*) malloc(byte-size)
One very significant difference in malloc() and calloc() is :
While malloc() allocates a single block of storage space with garbage (or random) values, calloc() allocates allocates multiple blocks of storage, each of the same size, and then sets all bytes to zero.

Organizing string of int - using debugger

as i stated before, i am learning C from home, and hitting some bumps on the way. Thanks to you all i am learning bit by bit.
I wrote something that made sense in my head and taking in account what i've learned so far:
int exercicio4a(int *s){
int tmp, i;
int nmax = strlen(s);
int z[nmax];
for(i=0; i!=nmax; i++){
if(s[i]>=s[i+1]){
z[i]=s[i+1];
}else{
z[i]=s[i];
}
}
return z;
}
main(){
int x, y, nmax;
int str[10];
printf("Organize a bunch of numbers:\n");
nmax = 9;
while(nmax!=0){
printf("Enter the random int number %d :\n", nmax);
scanf("%d", &str[nmax]);
nmax--;
}
printf("%s \n", exercicio4a(str) );
}
Needless to say that this is garbage as it doesn't take me anywhere!
One last thing, i would like to know if there is a way to use GDB in order to detect a malfunction in this code for example.
Cheers!
Well, you need to clarify your terms. You want to sort an array of integers, which you scan from stdin, I assume. Don't call this array a string, it is bad terminology. You also need to decide if exercicio4a should return a string of ascii characters, where the integers are inserted into a string, or an array of integers.
You really should be taking an integer array for your function and either sorting in place, or allocating a new one and returning it.
Now let's look at the problems with your code:
nmax = 9;
while(nmax!=0){
printf("Enter the random int number %d :\n", nmax);
scanf("%d", &str[nmax]);
nmax--;
}
You are exiting the loop when nmax == 0, but you never scan an integer into that location. To fix this:
nmax=10;
while (nmax--) {
//printf
scanf("%d", str + nmax); //or &str[nmax]; these are equal
}
Next: int exercicio4a(int *s){... This signature is incorrect. Assuming you don't want to sort in place, you want to return a new array so you should have int *exercicio4a(int *s){... You want to return a pointer to the first integer in the array.
Next int z[nmax]; This array is a local variable. It will go out of scope when you return from the function so the behavior of using it after you return is undefined! Instead you want to dynamically allocate space for the sorted array using int *z = calloc(nmax, sizeof(int)); You will need to free the returned array after the calling function is done using it to avoid memory leaks.
Next: printf("%s \n", exercicio4a(str) ); Here you are trying to print an integer as a string (with the code you have). Even if you fix it to return an int* you will still be trying to print an array of integers as a string. What you should do is use a loop to print the array:
nmax = 10;
int *ptr = exercicio4a(str); //only after you fix exercicio
while (nmax--)
printf("%d ", *ptr++);
Lastly, your loop does not perform a sort. It is an attempt to swap adjacent elements that are out of order. It does not perform this functionality correctly, but don't bother getting that working since it won't even implement a sorting algorithm. I suggest you read about insertion, bubble, and selection sort to get a feel for how to implement those algorithms if you want to learn how to do sorts on your own. Most of the time though, you will want to use a library function to sort an array. If you want to keep an un-sorted copy of your data, make a qsort wrapper:
int compare (void *one, void *two) {
return *(int *)one - *(int *)two;
}
int *my_sort(int *arr, int size) {
int *sorted = calloc(size, sizeof(int));
memcpy(sorted, arr, size * sizeof(int));
qsort(sorted, size, sizeof(int), compare);
return sorted;
}

Cannot return int array

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");
}

Return an array with all integers from a to b

The exercise says "Create a function with two parameters a and b which are integers and the function will return an array of integers with every number from a to b.
#include <stdio.h>
#include <stdlib.h>
void exc(int a, int b){
int i,k=0,d[k];
for(i=a;i<=b;i++){
d[k]=i;
k++;
printf("%d ",d[k]);
}
}
int main(void){
int c,d;
printf("Give first integer: ");
scanf("%d",&c);
printf("Give second integer: ");
scanf("%d",&d);
exc(c,d);
system("pause");
}
The problem is that if I put for example c=2 and d=5 the program returns something like 2088806975 16384 1 2293536 instead of 2 3 4 5. Where is the problem? Thanks
For starters
If your main() has return type int, don't forget to return a value from it!
int main(void)
{
/* code here */
return 0;
}
Problem 1
By
d[k]=i;
k++;
printf("%d ", d[k]);
I think you meant
d[k]=i;
printf("%d ", d[k]);
k++;
otherwise you're printing the "next" array element each time, which will be one-past-the-end of the array on the last loop iteration.
Problem 2
int i,k=0,d[k];
You make an array d of size k where k is 0. I think you intended for the array to automatically resize when you write k++, but this is not the case. The array is created with zero elements, and then that's its size for all time.
Your next instinct may be to create the array big enough in the first place:
int d[b-a+1];
Unfortunately, this is most likely wrong, too. It relies on a feature called Variable Length Arrays (or "VLAs"); although a GCC compiler extension (and, incidentally, C99) does allow this (and it's not clear whether you have that extension enabled and/or are allowed to use it in your homework — I will assume for this answer that you do not / are not), the language itself does not allow an array with a dynamic size.
What do I mean by dynamic size?
I mean that the variables a and b depend on user input: they are not known at compile-time. In general, the size of an array must be known at compile-time.
Note: If you use this, your code may compile without error, and your program may even appear to run and work correctly. However, you'd be relying on what's called "Undefined Behaviour", and your code could stop running or even crash at any time, due to any number of random, unpredictable factors. Even if it looks like it's okay, it's invalid. Don't do it!
Solution
Fortunately, there is a way to allocate a block of memory with the right size for your elements, when you don't know the elements until your program runs. It's called "dynamic allocation", and it involves a function call:
int *d = malloc(sizeof(int) * (b-a+1));
You can use the same syntax (d[k]) to access "elements" in this "array" or block of memory, but you must later manually free the memory:
free(d);
Possible problem 3
Your assignment says to return an array from the function, but you're not doing this. Instead, you're just creating, filling and printing the array all within the same function (which seems a bit pointless).
You can't actually return an array either, but since you're dynamically allocating the space for it, you have a pointer to work with. It's my opinion that your teacher may have wanted you to return a pointer to this array.
If so, the finished code looks a bit like this:
#include <stdio.h>
#include <stdlib.h>
int *exc(int a, int b)
{
int i, k = 0;
int *d = malloc(sizeof(int) * ((b-a)+1));
for (i=a; i<=b; i++) {
d[k]=i;
k++;
}
return d;
}
int main(void)
{
int a,b,i,*ar;
printf("Give first integer: ");
scanf("%d",&a);
printf("Give second integer: ");
scanf("%d",&b);
ar = exc(a,b);
for (i=0; i < (b-a+1); i++) {
printf("%d ", ar[i]);
}
free(ar);
system("pause");
return 0;
}
Disclaimer: I'm rusty on C, so the finished code might have a few syntax bugs.
Hope this helps!
The size of d is always 0. Since you are initializing it as d[k]. You should instead do something like d[b-a+1].
Update:
Furthermore, the order of your statements are wrong, see pmg's answer.
Update 2:
Your code doesn't actually return the array you are creating and it won't work unless you create the array on the heap (ie. using malloc / free).
The order of statements is not correct
d[k]=i; // d[0] = 42;
k++; // ...
printf("%d ",d[k]); // print d[1]
You need to allocate the memory for the array first, use malloc with the amount of integers you need to assign
Also, to be true to the problem statement, have the function return a pointer to the array so the main function can print it out instead of the exec function doing it directly.
Doing somebodys homework is always somewhat bad but obviously OP has no idea how to aproach this particular problem so here is a full example of dynamic memory allocation (overly commented).
#include <stdio.h>
#include <stdlib.h> /* required for malloc() and free() */
/* function that retuns a pointer to int type of data */
int *create_array(int a, int b)
{
int *array;
int array_size = b - a + 1; /* assuming that 'a' is always smaller than 'b' */
int i;
array = malloc( array_size * sizeof(int) ); /* allocate memory for the array */
if(array == NULL) exit(EXIT_FAILURE); /* bail out if allocation fails */
/* assign the values into array */
for(i = 0; i < array_size; ++i)
array[i] = a++;
/* return a pointer to our allocated array */
return array;
}
int main(void)
{
int *array;
int i, a = 42, b = 50;
/* and now we can call the function to create the array */
array = create_array(a, b);
/* print results */
for(i = 0; i < b - a + 1; ++i)
printf("%d\n", array[i]);
/* always remember to free the data after you are done with it */
free(array);
return 0;
}
You incorrectly declare d array in your code:
int d[k];
should be:
int d[b-a+1];
Edit::
Also, as others have posted, the statement order is wrong:
d[k]=i;
k++;
printf("%d ",d[k]);
should be:
d[k]=i;
printf("%d ",d[k]);
k++;
because otherwise you "lose" the first value when k==0.
You made an array of size zero and then started throwing data in without resizing the array. I'm a bit surprised that you aren't getting an error.
You're accessing data from memory outside the safety of defined data storage. It should be an error because the results are not defined. The data past the end of your array could be used for anything. And since your array is size zero, everything is past the end.
There are a couple problems. First, d is not returned from exc. Of course, you shouldn't just return it since it's allocated on the stack. Secondly, the printf is called after you increment k. That prints the next element in d, not the one whose value you just filled in. Finally, d doesn't have any space allocated for it, since k is always 0 when d is created.
It happens because you allocate memory for d on the stack. If you move the declaration of it outside the function, everything shoud be ok.

Resources