Wrong results with dynamic memory allocation - c

I am trying to find out the Lagrange's Interpolation with the program. I have solved it using arrays but when using dynamic memory allocation, the program is giving me garbage result.
#include<stdio.h>
#include<conio.h>
#define SIZE 100
int main()
{
float *x,*y;
float value = 0,ask,temp;
int i,j,n;
printf("Enter size");
scanf("%d",&n);
x = (float*)malloc(n*sizeof(float));
y = (float*)malloc(n*sizeof(float));
for(i = 0; i < n;i++)
{
printf("x[%d]: ",i);
scanf("%f",(x+i));
printf("y[%d]: ",i);
scanf("%f",(y+i));
}
printf("Enter value to find");
scanf("%f",&ask); //cin >> ask;
for(i = 0; i < n;i++)
{
temp = 1;
for(j = 0; j < n; j++)
{
if(i != j)
{
temp = temp * (ask-(*(x+i))/(*(x+i)-*(x+j)));
}
}
value = value + temp * *(y+i);
}
printf("%f",value);
}

You need to #include <stdlib.h>, since that is the header that declares functions that perform dynamic memory allocation (malloc(), etc).
You will find, assuming you use a C compiler and not a C++ compiler, that the type conversions on the malloc() calls are not required.
x = (float*)malloc(n*sizeof(float)); /* (float *) is unnecessary */
The problem is that, without stdlib.h, the compiler assumes malloc() returns an int. The type conversion might allow the code to compile without stdlib.h, but the result is subsequent usage of the malloc()d pointer will have undefined behaviour, since the pointer does not necessarily survive the round trip (being converted to int and then back).
If you are using a C++ compiler, then the (float *) type conversion AND #include <stdlib.h> are BOTH required to avoid undefined behaviour.

Related

How can static array in C taking size in runtime?

I am mindblown by this small code:
#include <stdio.h>
int main()
{
int limit = 0;
scanf("%d", &limit);
int y[limit];
for (int i = 0; i<limit; i++ ) {
y[i] = i;
}
for (int i = 0; i < limit; i++) {
printf("%d ", y[i]);
}
return 0;
}
How on earth this program is not segment-faulting as limit (size of the array) is assigned at runtime only?
Anything recently changed in C? This code shouldn't work in my understanding.
int y[limit]; is a Variable Length Array (or VLA for short) and was added in C99. If supported, it allocates the array on the stack (on systems having a stack). It's similar to using the machine- and compiler-dependent alloca function (which is called _alloca in MSVC):
Example:
#include <alloca.h>
#include <stdio.h>
int main()
{
int limit = 0;
if(scanf("%d", &limit) != 1 || limit < 1) return 1;
int* y = alloca(limit * sizeof *y); // instead of a VLA
for (int i = 0; i<limit; i++ ) {
y[i] = i;
}
for (int i = 0; i < limit; i++) {
printf("%d ", y[i]);
}
} // the memory allocated by alloca is here free'd automatically
Note that VLA:s are optional since C11, so not all C compilers support it. MSVC for example does not.
This doesnt compile in visual studio because limit "Error C2131 expression did not evaluate to a constant"
If you make limit a constexpr though then the compiler will not mind because youre telling it it wont change. You cant use 0 though as setting an array to a constant size length zero is nonsence.
What compiler does this run on for you ?

Does this free() function clean the memory?

I need your help, becouse I dont know whether I realy free the allocated memory. I also will be very grateful, if you could advice me some tools for this purpose. Thanks!
P.S You can skip bb_sort and swap functions.
#include <stdio.h>
#include <stdlib.h>
typedef struct DArray{
double * array;
int size;
} DArray;
void getArrays(DArray * arrays, int numOfArrays){
int curArraySize, i;
while(numOfArrays >= 0){
printf("Input size of array: "); scanf("%d", &curArraySize);
if(arrays[numOfArrays].array = (double*)malloc((arrays[numOfArrays].size = curArraySize)*sizeof(double))){
for(i = 0; i < arrays[numOfArrays].size; ++i)
arrays[numOfArrays].array[i] = rand()%100;
--numOfArrays;
}
else{
printf("Error, have no enough memory in the system!"); break;
}
}
}
void swap(double * arr, int pos1, int pos2) {
int tmp = arr[pos1];
arr[pos1]=arr[pos2];
arr[pos2]=tmp;
}
double * bb_sort(double * arr, int size){
int i, j, noChanges = 1;
while(1){
for(i = 0;i < size;++i){
for(j = 0;j < size-1;++j){
if(arr[j] < arr[j+1]){
swap(arr, j, j+1);
noChanges = 0;
}
}
if(noChanges) return arr;
noChanges = 1;
}
}
}
int main() {
srand (time (NULL));
int numOfArrays, i, j;
printf("Input number of arrays: "); scanf("%d", &numOfArrays);
DArray arrays[numOfArrays];
getArrays(arrays ,numOfArrays-1);
for(i = 0; i < numOfArrays; ++i){
bb_sort(arrays[i].array, arrays[i].size);
}
for(i = numOfArrays-1; i >= 0; --i){
printf("\nSorted array num#%d\n", i+1);
for(j = 0; j < arrays[i].size; ++j)
printf(" %.1lf ", arrays[i].array[j]);
free(arrays[i].array); <------FREE MEMORY?
printf("\n");
}
printf("Done!");
while(1){
}
return 0;
}
=====================================================================================================
Short Answer:
The OP ask if 'memory is cleaned'. Technically, there is no requirement for the free implementation to CLEAN the memory (e.g, sets the data to zero, or some random data). Most implementation will not CLEAR to memory to save time.
If, by mistake, the code will try to read the data, it will usually find the data is still in memory, potentially modified by the free call, or by other code, which was assigned the freed memory to other tasks.
For security sensitive information (password, credit card numbers, private keys), it is common to ZERO the data, or to fill the region with other pattern, before calling free. It will make it harder/reduce the risk of the data being access by mistakes, bugs or hacking.
Some memory debuggers will fill freed memory with pattern data/guards/etc, to help detect memory problems earlier than later.
Yes it will, since your program created array pointer using malloc function, and it does not manipulate that pointer, according to C99 standard (ISO/IEC 9899:1999):
7.20.3.2 The free function (p: 313):
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

Understanding why it does not find duplicates in array

I wrote the following function in C:
int last(long arr[], int length) {
for (int i = 0; i < length-1; i++)
if (*(arr+i) == *(arr + length - 1))
return 1;
return 0;
}
it checks if the last value of the array was used more than once. In the main:
int *arr = malloc(length*sizeof(int));
for (int i = 0; i < length; i++)
scanf("%d", ++arr);
printf(last((long *) arr, length);
For some reason for the array [1,2,2,3] it returns that the last element was used multiple times and I'm not sure why. I think that is because of scanf("%d", ++arr); but I don't know how to fix it.
My goal is that it will return 1 for [1,3,2,3] and 0 for [1,2,2,3]. What could be the problem?
You should use scanf("%d", &arr[i]);. Using ++arr causes the array to be incremented before you pass it to last, and also reads into data beyond arr, which is undefined behavior.
Another one of the issues in this is the cast to long *.
You should use %ld in scanf and long *arr = malloc(length*sizeof(*arr));.
Also make sure to check for NULL. You never know when malloc is going to fail or someone's going to pass bad data.
Full example:
#include <stdio.h>
#include <stdlib.h>
int last(long arr[], int length) {
if(!arr) return -1;
for (int i = 0; i < length-1; i++)
{
if (arr[i] == arr[length-1])
return 1;
}
return 0;
}
int main(void)
{
long *arr = malloc(4*sizeof(*arr));
if(!arr) return 1;
for (int i = 0; i < 4; i++)
scanf("%ld", &arr[i]);
printf("%d\n", last(arr, 4));
}
Several problems in your code:
Look at this statement:
scanf("%d", ++arr);
^^^^^
In the last iteration of loop, the pointer arr will be pointing to one element past end of array arr (due to pre-increment) and it is is passed to scanf(). The scanf() will access the memory location pointed by the pointer which is an invalid memory because your program does not own it. This is undefined behavior. Note that a pointer may point to one element past the end of array, this is as per standard but dereferencing such pointer will lead to undefined behavior.
Once the main() function for loop finishes the arr pointer pointing to location past the end of memory allocated to arr and just after this you are passing arr to last() function. So, you are passing an invalid memory reference to last() function and then accessing that memory in last() function - one more undefined behavior in your program.
Probably you should take another pointer and point it to arr, so that arr keep pointing to allcoated memory reference returned by malloc().
Note that if you want to read the input the way you are doing then use the post-increment operator in scanf(), like this:
int *arr = malloc(length*sizeof(int));
if (arr == NULL)
exit(EXIT_FAILURE);
int *ptr = arr;
for (int i = 0; i < length; i++)
scanf("%d", ptr++);
but the more appropriate and readable way is - scanf("%d", &arr[i]).
Another big problem in your code is accessing the int values as long type.
The last() function parameter arr type is long and you are passing it int pointer typecasted to long *.
Note that the size of long and int may be different based on the platform. You cannot assume them to be of same size on all platforms.
Assume the case where int size is 4 bytes and long size is 8 bytes.
In this case, when accessing an int pointer using long type pointer then every object will be considered as 8 byte long and when you do arr+1 in last(), the pointer will be advance by 8 bytes and you will never get correct result.
Compiler must be throwing warning message on this statement:
printf(last((long *) arr, length);
because the printf() expects first argument as const char * and you are passing it int (return type of last()). You should give the first argument to printf() a string which contains appropriate format specifier('s).
Putting these altogether:
#include <stdio.h>
#include <stdlib.h>
int last(int arr[], int length) {
if (arr == NULL) {
return 1;
}
for (int i = 0; i < length - 1; i++) {
if (arr[i] == arr[length - 1]) {
return 1;
}
}
return 0;
}
int main(void) {
int length = 4;
int *arr = malloc (length * sizeof (*arr));
if (arr == NULL) {
exit(EXIT_FAILURE);
}
printf ("Enter %d numbers:\n", length);
for (int i = 0; i < length; i++) {
scanf ("%d", &arr[i]);
}
printf ("Duplicate found: %s\n", last (arr, length) == 1 ? "Yes" : "No");
return 0;
}

Dynamic memory allocation repetition in C

I am somewhat new to C programming. I have a doubt regarding dynamic memory allocation. The following is a code in the main program for memory allocation.
double **mat=(double**)malloc(sizeof(double*)*n);
mat[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
mat[i] = mat[i-1] + n;
mat = create_square_matrix(n);
I want to call the function and create elements in the matrix inside the function. Do I have once again allocation memory inside the function like below or Is there any other method to avoid this tedious memory allocation repetition. Following is the function.
`double** create_square_matrix(int n)
{
int i,j,sum=0;
double **array2=(double**)malloc(sizeof(double*)*n);
array2[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
array2[i] = array2[i-1] + n;
for (i = 0; i < n; ++i)
{
for (j = 0; j < n; ++j)
{
sum=sum+j;
array2[i][j]=sum;
}
}
return array2;
}
`
The above function returns the array which is stored in the 'mat' variable. And another question is how do I free the memory of variable 'array2' inside the function after using the return method. I can't free the memory possibly before returning the array. Is there a method to free the memory in the above function.
Your function create_square_matrix allocates memory and then fills it by some values.
Your top piece of code allocates memory, and then calls create_square_matrix which again allocates memory. It is like to mop floors before calling the janitor who also mops floors. You don't need to allocate memory twice. Not only it is unneccessary, in fact it is bad. Since you perform two allocations, the memory from the first one is lost, and there is no way to free it. This is called memory leak. Instead of
double **mat=(double**)malloc(sizeof(double*)*n);
mat[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
mat[i] = mat[i-1] + n;
mat = create_square_matrix(n);
you should write
double **mat = create_square_matrix(n);
As mentioned, in C there's no need to cast to/from void*. Also, your calloc is backwards: use N elements for the first argument, sizeof(element) for the second.
I will answer your question, and then suggest a better approach.
You are choosing double ** for your matrix. Even if it weren't square, you know exactly how many pointers and how many doubles you need, and of course how big each type is. So,
double **M = malloc( n * sizeof(double*) + n * m * sizeof(double) );
does the trick, does it not? If sizeof(double*) == sizeof(double) for your machine (probably true), then
double **M = calloc( (1+n) * m, sizeof(double) );
works, too, but less portably. You also get the zeros for free; you'll have trouble finding a machine for which it's not true that double f=0 yields a value for which all bits are zero.
But why define your matrix as an array of pointers? Why not instead define it as an array of doubles?
double *M = calloc( n * m, sizeof(double) );
Better yet, for the past 15 years or so, C has supported variable-length arrays, meaning you can define arrays whose size is determined at runtime. Back in K&R days, you could define an array M[n] unless n was a static constant or enum. If your arrays aren't ginormous -- meaning that for the machine in question they'll fit comfortably on the stack -- you can skip malloc and simply define your matrix by a size determined at runtime.
Even if you can't do that, can typedef one dimension dynamically,
typedef double (x_axis_t)[m];
double x_axis_t *M = calloc( n * sizeof(x_axis_t), sizeof(double) );
which is nice, because then you can access your array as
M[x][y];
Just don't try to use M[x,y], because that's something else altogether.
BTW, since you're new to the game, to use a c99 compiler, the standard command is c99, not cc. See your friendly manual for details. :-)
Using a nice function macro for memory allocation is always a good idea. Unless you have to free memory manually I would leave it to a garbage collector such as libgc. Below is an example. If you don't want to use a garbage collector you can just replace GC_MALLOC with malloc. When you free the array (manually) you must first free the individual rows.
#include <gc/gc.h>
#include <stdio.h>
#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = GC_MALLOC((n) * sizeof (ptr)[0])
double **SquareMatrix(int n)
{
double **A;
int i, j;
NEW_ARRAY(A, n);
for (i = 0; i < n; i++) {
NEW_ARRAY(A[i], n);
for (j = 0; j < n; j++) {
A[i][j] = 0.0;
}
}
return A;
}
int main(void)
{
const int n = 5;
double **A;
int i, j;
A = SquareMatrix(n);
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
printf("%5.2f ", A[i][j]);
}
putchar('\n');
}
return 0;
}

Is it possible to trully force a variable to become constant to allow me declaring arrays dynamically?

I did some googling and I'm pretty sure this is impossible in C, as constants are created during the compiling..
Anyways, I would still like to ask it it's possible. I would like to generate arrays in a loop with loop defined length like this:
#include <stdio.h>
#define ROWCOL_MULTIPLIER 50
main() {
for (int loop = 0; loop < 11; loop++) {
const int val = loop * ROWCOL_MULTIPLIER;
double b[val] = malloc(sizeof(double)* val * val);
// do foo things
free(b);
}
return 0;
}
This is what I needed to accomplish http://ideone.com/fork/TyGZVV
#include <stdio.h>
#include <stdlib.h>
#define ROWCOL_MULTIPLIER 1
main() {
size_t loop, i, j = 0;
for (loop = 0; loop < 5; loop++) {
const double val = (loop + 1) * ROWCOL_MULTIPLIER;
double *column_sum = malloc(val * sizeof *column_sum);
double *p = malloc(val * val * sizeof *p);
printf("\n%i\n", loop + 1);
for (i = 0; i < val; ++i){
column_sum[i] = *(double*)&i;
for (j = 0; j < val; ++j){
int index = i * (int)val + j;
p[index] = *(double*)&j;
double offsetI = column_sum[i];
double offsetJ = p[index]++;
printf("%d->", offsetI);
printf("%d,", offsetJ);
}
printf("\n");
}
free(p);
free(column_sum);
}
}
In C89, double b[val] is illegal, because a const variable does not count as a compile-time constant.
In any version of C, double b[val] = malloc... is illegal because an array can only be initialized by values matching its element type. An array of doubles can contain things like 3.1, 7.2 - not malloc.
In C99 you can write:
double b[val];
which is an array of val doubles. If you want val * val doubles you can write double b[val * val];, or double b[val][val]; or anything else along those lines. This array uses automatic storage (sometimes called stack) and is freed when the code block including this definition ends.
In any version of C you can use dynamic storage. In that case you must use a pointer to refer to the storage, e.g.:
double *p = malloc( val * sizeof *p );
double *p = malloc( val * val * sizeof *p );
In C99 you can combine malloc with variably-modified types, this will let you use 2-D array access syntax:
double (*p)[val] = malloc(val * sizeof *p);
for (size_t i = 0; i < val; ++i)
for (size_t j = 0; j < val; ++j)
p[i][j] = 0.0;
There is a major difference between a compile-time constant and a const variable: The compile-time constant can (duh!) be computed at compile time. For the C compiler, this means that the amount of space that must be reserved for an array of size X can be computed if X is a compile-time constant. If X is simply const then amount of space to reserve for the array cannot be known at compile time.
Since the C compiler essentially creates a struct for each automatic storage frame, and since the size of all the elements of a struct must be known at compile time, if you want to declare an array that is allocated in automatic storage it must have a size that is a compile-time constant. Similarly, if you want to declare an array that is allocated as a part of a struct or class, its size must be known at compile time.

Resources