Error when freeing memory [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am writing some code to compute the sum of fibonacci values up to n, as stored in an array. For only certain values of n, I get an error on calling free().
Edit: This code should now compile.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long fib(long *fibs, int n);
int main(int argc, char *argv[]) {
long num, sum;
long n;
long *fibs;
if(argc < 2) {
printf("Usage %s n\n", argv[0]);
exit(EXIT_SUCCESS);
}
n = strtol(argv[1], NULL, 10);
printf("%ld\n", n);
printf("--Allocating memory\n");
fibs = (long *) malloc(sizeof(long) * n);
printf("--Memory allocated\n");
fibs[0] = 1;
fibs[1] = 1;
sum = 0;
for(int i = 0; i <= n; i++) {
num = fib(fibs, i);
sum += num;
printf("%ld\n", num);
}
printf("%ld\n", sum);
printf("--Freeing memory\n");
free(fibs);
printf("--Memory freed\n");
}
long fib(long *fibs, int n) {
if((n == 0) || (n == 1)) {
return 1;
}
fibs[n] = fibs[n - 1] + fibs[n - 2];
return fibs[n];
}
For instance, when I call the program ./fibsum with n=5, I get a core dump.

The lines
fibs[n] = 1;
and
fibs[n] = fibs[n - 1] + fibs[n - 2];
modify memory beyond the legal range. The legal range is fibs[0] - fibs[n-1]. Due to that, the program displays undefined behavior. In your case, the undefined behavior manifests in the form of problem in the call to free.
You may want to allocate one more element than you are currently allocating. Instead of
fibs = (long *) malloc(n * sizeof(n));
use
fibs = malloc((n+1) * sizeof(n));
See an SO post on why you should not cast the return value of malloc.

Like i told you in the comments, you are overflowing when using <= instead of < in the loop. Take a look at the following example, this is by no means trying to be a "cleaned up" version of your code, I just made it work without changing too much.
#include <stdio.h>
#include <stdlib.h>
int number = 300;
long* fib(long* fibs, int n)
{
if (n == 0 || n == 1)
{
fibs[n] = 1;
}
else
{
fibs[n] = (fibs[n-1] + fibs[n-2]);
}
return fibs;
}
int main(int argc, char *argv[])
{
long* fibs = (long*)malloc(number * sizeof(long));
long sum = 0;
for (int i = 0; i < number; ++i) //changed <= to < like i said in the comments
{
sum += fib(fibs, i)[i];
printf("%d\n", sum);
}
printf("\n\nSum of everything: %ld\n", sum);
free(fibs); //no problem
return 0;
}

There are number of problems -
i is undeclared in main.
n is not declared in main.
And most important one this loop-
for(i = 0; i <= n; i++)
As you allocate memory for n items but loop goes from 0 to n .You forgot it should be till n-1 .Thus behaviour is undefined.
As case you described (n=5 so loop should be from 0 to 4).

There are few problems in your code, some are typing mistake I guess, some are logical problem:
You forgot to type n and i
Never cast malloc, so instead of fibs = (long *) malloc(n * sizeof(n)); try fibs = malloc(n * sizeof(long));
In the for loop, instead of for(i = 0; i <= n; i++) use for(i = 0; i < n; i++)
sum += fib(fibs, i); here, sum is long but fib() returns long *, so change function defalcation long *fib(long *fibs, int n) to long fib(long *fibs, int n)
I update your code then run and get output : 12.
The modified code:
#include <stdio.h>
#include <stdlib.h>
long fib(long *fibs, int n) {
if((n == 0) || (n == 1)) {
fibs[n] = 1;
} else {
fibs[n] = fibs[n - 1] + fibs[n - 2];
}
return fibs[n];
}
int main(int argc, char *argv[]) {
long *fibs;
long sum = 0;
int n = 6, i;
fibs = malloc(n * sizeof(long));
long tem;
for(i = 0; i < n; i++) {
tem = fib(fibs, i);
sum += tem;
}
printf("%ld\n", sum);
free(fibs);
}

Related

Finding the longest Collatz Chain

I am currently on my Uni homework and this is the last task. Its the 14th euler problem.
https://projecteuler.net/problem=14
So I am really new and i know that have a lot of crappy implementations. When executing this there is actually no output at all. I've been running this for 3 Minutes because i thought it needed to "load"..
My Task is to have a working function that calculates the Length and then take this length and compare it to have the longest chain as the "Final" output.
I tried to have a Loop that calculates the length for every i in 1000000 and then save this number into an array with the same size.
At the end of the Loop I want to compare the last length with the current and save the longer into the var if its longer.
I am stuck for like the past 2 hours
Here is my current Code:
#include <stdio.h>
#include <math.h>
int number = 1000000;
long sequence = 0;
int seqLen = 0;
int startingNum = 0;
int currLen = 0;
unsigned calculateCollatzLength(unsigned n){
int ans = 1;
while (n != 1) {
if (n & 1) {
n = 3 * n + 1;
} else {
n >>= 1;
}
ans ++;
}
currLen = ans;
return currLen;
}
int main() {
int cache[number];
for(int i = 0; i <= number; i++){
calculateCollatzLength(i);
cache[i] = currLen;
if (cache[i] > seqLen) {
seqLen = cache[i];
startingNum = i;
}
}
printf("The Longest Collatz Chain from 1 to 1000000 is %d long and has the starting number %d \n", seqLen, startingNum);
}
Hope that this is kind of understandable to ask in on this since this is my 3rd Question and it kind of feels like cheating asking but i dont know who to ask or cant find any answers :(
Here's a cleaned-up working version of your code. There's no need for a cache, and int64_t is a safer bet than unsigned (which is likely to be 32 bits) to avoid overflows. Your use of global variables was confusing and unnecessary – you can simply return the length of the sequence and find the maximum in main.
#include <stdio.h>
#include <stdint.h>
int collatz(int64_t n){
int len = 1;
while (n != 1) {
if (n & 1) {
n = 3 * n + 1;
} else {
n >>= 1;
}
len++;
}
return len;
}
#define N 1000000
int main(void) {
int longest_i = 0;
int longest = 0;
for(int i = 1; i <= N; i++){
int len = collatz(i);
if (len > longest) {
longest_i = i;
longest = len;
}
}
printf("**collatz(%d) = %d\n", longest_i, longest);
}

Printf function who returning an array of int

I'm trying this exercice but I don't know how to printf my function in main.
Exercice:
1) Write a function who returning an int tab with all values between min and max
#include <stdlib.h>
#include <stdio.h>
int *ft_range(int min, int max)
{
int len;
int *tab;
len = min;
while (len < max)
len++;
tab = (int *)malloc(sizeof(*tab) * len + 1);
while (min < max)
{
*tab = min;
min++;
}
return(tab);
}
int main()
{
ft_range(0, 10);
return(0);
}
returning an int tab with all values between min and max
Depending on the idea of "between", it is an open question if the end values should be included. Given OP's mis-coded +1 in sizeof(*tab) * len + 1, I'll go with the idea both ends should be included.
Miscalculation of len
Rather than loop, simply subtract
//len = min;
//while (len < max)
// len++;
len = max - min + 1;
Allocation miscalculated
Good to use sizeof *pointer, yet the + 1 makes little sense. If anything the ... * len + 1 should have been ... * (len + 1). Yet the +1 is handled with the above fix. Also cast not needed in C.
// tab = (int *)malloc(sizeof(*tab) * len + 1);
tab = malloc(sizeof *tab * len);
Wrong assignment
Code repeatedly assigned the same *tab location.
//while (min < max)
//{
// *tab = min;
// min++;
//}
for (int i = min; i <= max; i++) {
tab[i - min] = i;
}
No allocation error checking nor min, max validation
Potential for int overflow with mix - min
Be sure to free allocations
Alternative
#include <stdlib.h>
#include <stdio.h>
int *ft_range(int min, int max) {
if (min > max) {
return NULL;
}
size_t len = (size_t)max - min + 1;
int *tab = malloc(sizeof *tab * len);
if (tab == NULL) {
return NULL;
}
for (size_t i = 0; i < len; i++) {
tab[i] = int(min + i);
}
return tab;
}
int main() {
int mn = 0;
int mx = 10;
int *ft = ft_range(mn, mx);
if (ft) {
int *p = ft;
for (int i = mn; i <= mx; i++) {
printf("%d ", *p++);
}
free(ft);
}
return 0;
}
inside "ft_range", when you are trying to calculate the length the array needs to do, all you have to do is subtract the minimum from the maximum. what you did is much slower and unnecessary.
when allocating memory, you did not need to add a "+1" at the end. you may have seen it done in other examples, but it does not apply here.
the "while" loop inside "ft_range" needs to have a "<=" sign, otherwise it will stop before it reaches the "max" value.
when adding a value to the "tab" int array, you are always doing so by dereferencing it (putting a "*" before it), so every one of your values will come on the first position of the array and overwrite themselves. you need to have another "int i" to keep track of the current index of the array.
make sure to free the memory you allocated with "malloc" after you finish your enumeration. it does not matter right now, but if you ever get to writing more complex programs you will need to do so to keep the performance up, which can be critical.
here's a working code, with a few comments (i'm shit at comments, if you don't understand them, just ask me bro)
#include <stdlib.h>
#include <stdio.h>
int *ft_range(int min, int max)
{
int len;
int * tab;
len = max-min;
tab = (int *)malloc(sizeof(*tab) * len);
// create an index to track the position inside "tab"
int i = 0;
// sign needs to be "<=" so it does not stop before it reaches the max value
while (min <= max)
{
tab[i] = min;
// ++ needs to come before so the variable's value is updated right here
++min;
// increase the i index to the next position in "tab"
++i;
}
return(tab);
}
int main()
{
int min = 5;
int max = 10;
int len = max-min;
int * range = ft_range(min, max);
for(int i = 0; i <= len; ++i)
{
// %d = integer
// \n = move to next line
printf("%d\n", range[i]);
}
getchar();
return(0);
}
You correctly allocate memory to the table, you just need to printf the value in your main by using a loop trough your tab, i write this code who work perfectly.
#include <stdlib.h>
int *ft_range(int min, int max)
{
int *ptr;
int mi;
int i;
int range;
range = (max - min);
mi = min;
ptr = NULL;
if (min > max)
return (NULL);
else
ptr = malloc(sizeof(int) * range);
i = 0;
while (i < range)
{
ptr[i] = mi + i;
i++;
}
return (ptr);
}
// #include <stdio.h>
// int main()
// {
// //int i = 0;
// int min = 1;
// int max = 30;
// while(min < max)
// {
// printf("%d\n", *ft_range(min, max));
// min++;
// }
// }

variable sized object may not be initialized

I am getting the error variable sized object may not be initialized and I don't understand why.
Could someone show me how to fix this line?
int arr[size] = (int *)(augs->one);
Here is my code:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>
int count = 0;
int cmpfunc(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
struct structure {
int two;
int *one;
};
void *sort(void *augments) {
struct structure *augs = (struct structure*)augments;
int i = 0;
int size = 1;
size = augs->two;
int arr[size] = (int *)(augs->one);
//int *arr = (int *)data;
//printf("sizeof:%d\n", sizeof(arr));
qsort(arr, size, sizeof(int), cmpfunc);
printf("finaloutput:\n");
for (i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return NULL;
}
int main(int argc, char *argv[]) {
FILE *myFile;
myFile = fopen("data.txt", "r");
// number of lines in file
char charicter;
for (charicter = getc(myFile); charicter != EOF; charicter = getc(myFile)) {
if (charicter == '\n') {
count++;
}
}
printf("count is %d\n", count);
int numberArray[count];
int i = 0;
if ((myFile = fopen("data.txt", "r"))) {
while ((fscanf(myFile, "%d", &numberArray[i]) != EOF)) {
++i;
}
fclose(myFile);
}
assert(argv[1] != NULL);
int num = atoi(argv[1]); //num equals number input
int arrayarray[num - 1][(count / num)];
int idx;
for (i = 0; i < (count); i++) {
printf("numberarray[%d]= %d\n", i, numberArray[i] /*[0],numberArray[i][1]*/);
}
for (i = 1; i < num + 1; i++) {
for (idx = 0; idx < (count / num); idx++) {
arrayarray[i - 1][idx] = numberArray[i * idx];
}
}
///*
for (i = 0; i < ((count / num)); i++) {
printf("arrayarray[0]=%d\n", arrayarray[0][i]);
}
//*/
int lastarray[((count / num) + (count % num))];
for (idx = 0; idx < ((count / num) + (count % num)); idx++) {
lastarray[idx] = numberArray[idx + ((count / num) * (num - 1))];
}
for (i = 0; i < ((((count / num) + (count % num)))); i++) {
printf("lastaray[%d]=%d\n", i, lastarray[i]);
}
//*******************
pthread_t thread_id_arr[num];
for (i = 0; i < num; i++) {
pthread_t tid;
struct structure *augs;
if (i != (num - 1)) {
augs = malloc(sizeof(struct structure) + sizeof(int) + sizeof(int) * num);
(*augs).one = arrayarray[i];
(*augs).two = (count / num);
pthread_create(&tid, NULL, sort, augs);
} else {
(*augs).one = lastarray;
(*augs).two = (count / num) + (count % num);
pthread_create(&tid, NULL, sort, augs);
//pthread_create(&tid, NULL, sort, (void*)lastarray);
}
thread_id_arr[i] = tid;
}
for (i = 0; i < num; i++) {
pthread_join(thread_id_arr[i], NULL);
}
return 0;
}
As others pointed out, you can't initialize a Variable Length Array with a pointer, like you are doing. However, you don't actually need a VLA at all. Use this instead :
int *arr = augs -> one;
You want to act directly on the array that is passed into the thread, not make a copy of it.
That being said, I see another problem. In the loop that spawns the sorting threads, you are not allocating a new args on the last loop iteration, it reuses the allocated args from the previous iteration, which can cause disaster for the 2nd-to-last thread. You need to move the malloc() call above the if.
Also, the malloc() is allocating more memory than your threads actually use. You only need to allocate enough memory for just the struct by itself, not for any integers following the struct.
Also, when each thread is done using the allocated args that it is given, it needs to free() the args to avoid leaking memory.

Stuck in a for loop entering values to an array in C language

I am trying to practice with C by making a bubble sort program. The problem until now seems to be that the for loop that is giving values to the cells of the array is stuck after the condition is no longer fulfilled but it doesn't seem to be executing the commands in the loop. I don't know what is happening exactly and I have added some extra lines to see what is happening an these were my conclusions. Here is the code:
#include <stdio.h>
#include <stdlib.h>
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
int *sort(int *array)
{
int finish = 1;
while (finish = 1)
{
finish = 0;
for (int i = 0; i <= sizeof(array); i++)
{
if ((array + i) > (array + i + 1))
{
swap(array + i, array + i + 1);
finish = 1;
}
}
}
return array;
}
int main()
{
int s, res;
printf("Give me the size of the array being sorted(larger than 1) : ");
do
{
res = scanf("%d", &s);
if (res != 1)
{
printf("Wrong Input!\n");
exit(1);
}
if (s < 2)
printf("Only numbers equal or larger than 2\n");
} while (s < 2);
int array[s];
for (int i = 0; i < s; i += 1)
{
scanf("%d", array + i);
printf("%d %d %d\n\n", *(array + i), i, i < s); // I used this to check if my values were ok
}
printf("end of reading the array"); //I added this line to see if I would exit the for loop. I am not seeing this message
sort(array);
printf("\n");
for (int i = 0; i < sizeof(array); i++)
printf("%d\n\n", array + i);
printf("Array has been sorted! Have a nice day!\n\n************************************************************");
return 0;
}
See the annotations in the code:
#include <stddef.h> // size_t 1)
#include <stdio.h>
#include <stdlib.h>
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
int *sort(int *array, size_t size) // needs an extra parameter to know the size of the array
{
int finish = 1;
while (finish /* = 1 * you don't want assignment, you want comparison: */ == 1)
{
finish = 0;
for (int i = 0; i /* <= sizeof(array) */ < size - 1; i++) // i should be of type size_t
{
// if ((array + i) > (array + i + 1)) you are not dereferencing:
if(array[i] > array[i + 1])
{
// swap(array + i, array + i + 1); // easier to read imho:
swap(&array[i], &array[i + 1]);
finish = 1;
}
}
}
return array; // why does this function return anything? it is never used.
}
int main()
{
int s; /* , res; no need for an extra variable res */
printf("Give me the size of the array being sorted(larger than 1) : ");
do
{
// res = scanf("%d", &s);
// if (res != 1)
if (scanf("%d", &s) != 1)
{
printf("Wrong Input!\n");
// exit(1); // should be EXIT_FAILURE. Use return instead of exit() when in main().
return EXIT_FAILURE;
}
if (s < 2)
printf("Only numbers equal or larger than 2\n");
} while (s < 2);
int array[s];
for (int i = 0; i < s; /* i += 1* idiomatic: */ ++i) // size_t would be the correct type for s and i.
{
scanf("%d", /* array + i use indexes: */ &array[i]);
printf("%d %d %d\n\n", array[i], i, i < s); // again: indexes. i < s is allready ensured by the condition of the for-loop
}
printf("end of reading the array");
// sort(array); // sort will have no idea about the size of array use
sort(array, s); // instead.
printf("\n");
for (int i = 0; i < /* sizeof(array) 2) */ s; i++)
printf("%d\n\n", /* array + i * again you don't dereference */ array[i]);
printf("Array has been sorted! Have a nice day!\n\n************************************************************");
return 0;
}
1) size_t is the type that is guaranteed to be big enough to hold all sizes of objects in memory and indexes into them. The conversion specifier for scanf() is "%zu".
2) sizeof(array) in main() will yield the number of bytes in array, but you want the number of elements so you'd have to use sizeof(array) / sizeof(*array). But thats not needed since you already know its size. It is s.
This line
printf("end of reading the array");
has no line feed at the end of the string. This is a problem because printf is part of the family of functions called "buffered IO". The C library maintains a buffer of the things you want to print and only sends them to the terminal if the buffer gets full or it encounters \n in the stream of characters. You will not see, end of reading the array on your screen until after you have printed a line feed. You only do this after calling sort(). So all you know is your program is getting into an infinite loop at some point before the end of sort.
So there are actually three loops that could be infinite: the for loop you identified, the while loop in sort and the for loop inside the while loop. As the other answers point out, you have made the classic mistake of using assignment in the while conditional
while (finish = 1)
// ^ not enough equals signs
Unless your C compiler is really old, it is probably outputting a warning on that line. You should heed warnings.
Also, you should learn to use a debugger sooner rather than later. Believe me, it will save you a lot of time finding bugs.
In the sort function sizeof(array) returns the size of the pointer. (you can check it by yourself using printf("%d", sizeof(array).
The solution is to change your function to:
int sort(int* array, size_t size) { ... }
and call it with the correct array size:
sort(array, s);

Assigning a return value of a function in heap

I am having trouble with assigning a return value of a function in heap part of the program. When I tried it in main, it gives an error "Segmentation fault". I believe it is because of the size of my array, which is the return value that I mentioned earlier because when I make my max_size smaller, the code works correctly (I think up to 45000). When I call the function in main, it uses the memory of stack, which is much smaller than memory of heap. Therefore I tried to call the function in heap and make the assignment in there but the compiler gave an error
deneme.c:6:15: error: initializer element is not constant
int *primes = listPrimes(1000000, &size);
After that I did some research and found out that stack is 8 MB memory, which is around 8000000 bytes. Then I estimated my array size as using the prime number theorem (up to 1000000, there are approximately 200000 primes) and sizeof(int) = 4 bit value so it gives 100000 bytes, which is much less than 8 MB. Therefore I have two questions in mind:
1. Why the compiler gives segmentation fault error although my array size is not too large?
2. How can I make the assigment in heap instead of main in order to avoid this problem?
Here is my code:
#include "mathlib.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int *listPrimes(int max_size, int *size) {
*size = 1;
int *result = malloc(*size * sizeof(int));
int i;
int index = 1;
// Finding the list of primes using a sieve algorithm:
int *nums = malloc(max_size*sizeof(int));
for (i = 0; i < max_size; i++) {
nums[i] = i;
}
result[0] = 2;
int j = 2;
while (j < max_size) {
int k = j;
while (j*k <= max_size) {
nums[j*k] = 0;
k++;
}
if (j == 2) {
j++;
*size = *size + 1;
result = realloc(result, *size * sizeof(int));
result[index++] = nums[j];
}
else {
j += 2;
if (nums[j] != 0) {
*size = *size + 1;
result = realloc(result, *size * sizeof(int));
result[index++] = nums[j];
}
}
}
return result;
}
and main function:
#include <stdio.h>
#include <stdlib.h>
#include "mathlib.h"
int size = 0;
int *primes = listPrimes(1000000, &size);
int main() {
printf("size = %d\n", size);
for (int i = 0; i < size; i++) {
printf("%d th prime is %d\n", i+1, primes[i]);
}
free(primes);
return 0;
}
Use unsigned int for j, k and max_size in listPrimes and it works properly . Below is the tested code:
// #include "mathlib.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int size = 0;
int *
listPrimes (unsigned int max_size, int *size)
{
*size = 1;
int *result = malloc (*size * sizeof (int));
int i;
int index = 1;
// Finding the list of primes using a sieve algorithm:
int *nums = malloc (max_size * sizeof (int));
for (i = 0; i < max_size; i++)
{
nums[i] = i;
}
result[0] = 2;
unsigned int j = 2;
while (j < max_size)
{
unsigned int k = j;
while (j * k <max_size)
{
nums[j * k] = 0;
k++;
}
if (j == 2)
{
j++;
*size = *size + 1;
result = realloc (result, *size * sizeof (int));
result[index++] = nums[j];
}
else
{
j += 2;
if (nums[j] != 0)
{
*size = *size + 1;
result = realloc (result, *size * sizeof (int));
result[index++] = nums[j];
}
}
}
free(nums);
return result;
}
int
main ()
{
int *primes = listPrimes (1000000, &size);
printf ("size = %d\n", size);
for (int i = 0; i < size; i++)
{
printf ("%d th prime is %d\n", i + 1, primes[i]);
}
free (primes);
return 0;
}
nums is allocated to have max_size elements, so the index of its last element is max-size-1.
This loop:
while (j*k <= max_size) {
nums[j*k] = 0;
k++;
}
may access an element with index j*k that equals max_size, thus writing beyond the end of the array. The loop should be limited to j*k < max_size.
Regarding your second question, the size of the result array is determined while finding the primes and is not readily calculable in advance, so it cannot easily be allocated prior to calling listPrimes. It could be done by evaluating the prime-counting function, but that is likely more than you want to do for this project.

Resources