Hi, I'm a newbie in C (and in programming) and I'm trying to make a function that returns dynamically allocated array. It looks like:
int *returnArray(void)
{
int i, *p[4];
for (i = 0; i < 4; i++)
if ((p[i]=(int *)malloc(sizeof(int)*(4-i))) == NULL)
return NULL;
return &p[0][0];
}
And calling to this function:
int *ar;
if ((ar = returnArray()) == NULL) {
/* ERROR */
return 1;
}
But it doesn't work at all. After calling the function I wish to use *ar like a normal 2D array + unallocate the memory at the end of programme. Even if I've looked at similar topics I don't know how to fix it.
Thank you all for your help. I understand it much better now.
You're close. What you are missing is that you need to allocate both dimensions, like this:
int** CreateTwoDimensionalArray(int rows, int cols)
{
int row, prevrow;
int** result = (int**) calloc(rows, sizeof(int*));
if (result == NULL) {
return NULL;
}
for (row = 0; row < rows; ++row) {
int* current_row = (int*) calloc(cols, sizeof(int));
if (current_row == NULL) {
for (prevrow = 0; prevrow < row; ++prevrow) {
free(result[prevrow]);
}
free(result);
return NULL;
}
result[row] = current_row;
}
return result;
}
void FreeTwoDimensionalArray(int** array, int rows, int cols)
{
int row;
for (row = 0; row < rows; ++row) {
free(array[row]);
}
free(array);
}
In function returnArray, variable p is a local variable, so you should not return its address.
You can return one of the values in it (for example - p[2]), but you will obviously lose all the others.
So instead of returning this array, pass it to the function and initialize the entries inside:
void initArray(int* p[])
{
int i;
for (i=0; i<SIZE; i++)
p[i] = (int*)malloc(sizeof(int)*(SIZE-i));
}
Then, you can call this function and check if all allocations have completed successfully:
int i;
int* p[SIZE];
initArray(p);
for (i=0; i<SIZE; i++)
{
if (p[i] == NULL)
break;
}
if (i < SIZE)
{
//Error - not all allocations have completed successfully
}
else
{
// Example #1
scanf("%d",&p[3][0]);
printf("%d",p[3][0]);
// Example #2
scanf("%d" , p[3]);
printf("%d",*p[3]);
}
And of course, you will need to release the allocated memory at a later point in execution:
void freeArray(int* p[])
{
int i;
for (i=0; i<SIZE; i++)
{
if (p[i])
free(p[i]);
}
}
Related
I'm trying to write a program that calculates the number of elements of given matrix,for example M[2][3] = [1,2,3][3,4,5]
should give the number of elements from 0 trough 9 in a nxm array.
The algorithm is correct up until line 34(M[i][j] = i + 2;) in which I'm having a segmentation fault.
What am I doing wrong?
#include<stdio.h>
#include<stdlib.h>
#define ROW 10
#define COL 10
#define MAX 10
void Print_Matrix(int **M,int row,int col);
int MallocX(int **M,int row,int col);
int main(void)
{
int **M = 0x0;
int count[MAX] = {0};
int i,j;
if(MallocX(M,ROW,COL)){
fprintf(stdout,"Could not allocate memory\n");
exit(1);
}
for(i = 0;i<ROW;i++){
for(j = 0;j<COL;j++){
M[i][j] = i + 2;
}
}
Print_Matrix(M,ROW,COL);
for(i = 0;i<ROW;i++){
for(j = 0;j<COL;j++){
++count[M[i][j]];
}
}
for(j = 0;j<MAX;j++){
if(count[j]){
printf("%d %d\n",j,count[j]);
}
}
for(i = 0;i<ROW;i++){
free(M[i]);
}
free(M);
}
int MallocX(int **M,int row,int col)
{
int i;
M = (int **) malloc(row * sizeof(int *));
if(M == NULL){
fprintf(stderr,"Error allocating memory\n");
free(M);
return 1;
}
for(i = 0;i<row;i++){
M[i] = (int *) malloc(col * sizeof(int));
if(M[i] == NULL){
fprintf(stderr,"Error allocating memory\n");
free(M[i]);
return 1;
}
}
return 0;
}
void Print_Matrix(int **M,int row,int col)
{
int i,j;
for(i = 0;i<row;i++){
for(j = 0;j<col;j++){
printf("%d ",M[i][j]);
}
printf("\n");
}
}
This is because you are passing M by value, not reference. Your MallocX allocates memory for your matrix, but those allocations are orphaned when you return to the main program, where M is still 0x0 (or NULL), which is why allocation functions typically return a pointer. Perhaps you want something like this:
int **MallocX(int row,int col)
{
int **Matrix, i;
Matrix = malloc(row * sizeof(int*));
if(Matrix == NULL) {
fprintf(stderr,"Error allocating memory\n");
return NULL;
}
for (i = 0; i < row; i++) {
Matrix[i] = (int*) malloc(col * sizeof(int));
if(Matrix[i] == NULL){
fprintf(stderr,"Error allocating memory (%d)\n",i);
for (int j = 0; j < i; ++j)
free(Matrix[j]);
free(Matrix);
return NULL;
}
}
return Matrix;
}
Then in main, call it with:
if (!(M = MallocX(ROW,COL)) {
fprintf(stdout,"Could not allocate memory\n");
exit(1);
}
Note that in your original code, you were calling free(M) when M was NULL, which will itself cause a segfault. So I've tidied up your garbage collection a bit too.
I'm trying to add new element to dynamic array in C (I know that I must free all memory. I will do it later), but I get this error every time:
But, what is strange, if I compile from terminal, like that, code works properly.
So, where is the error and how i can beat it?
Thank you!
All my code:
main.c
#include <stdio.h>
#include <stdlib.h>
typedef struct vector
{
int size;
int *array;
int alreadyIn;
}vector;
vector *vectorInit(int size)
{
vector *newVec = (vector *)malloc(sizeof(vector));
if(!newVec){printf("No memory!\n"); return NULL;}
newVec->size = size;
newVec->array = (int *)malloc(size * sizeof(int));
return newVec;
}
void allocNewMemory(vector *vect, int howMuch)
{
vect->array = (int *)realloc(vect->array ,(vect->size + howMuch) * sizeof(int));
vect->size += howMuch;
}
void pushBack(vector *vect, int number)
{
int howMuch = 5;
if(vect && vect->alreadyIn < vect->size)
{
vect->array[vect->alreadyIn] = number;
vect->alreadyIn++;
}
else
{
printf("Alloc new memory for %d elements...\n", howMuch);
allocNewMemory(vect, howMuch);
pushBack(vect, number);
}
}
void printVector(vector *vect)
{
for (int i = 0; i < vect->alreadyIn; i++)
{
printf("%d ", vect->array[i]);
}
printf("\n");
}
int main()
{
int startSize = 4;
vector * vec = vectorInit(startSize);
for (int i = 0; i < 6; i++)
{
pushBack(vec, i+1);
}
printVector(vec);
return 0;
}
You never initialize the alreadyIn member in the structure. That means its value will be indeterminate (and seemingly garbage or random).
You need to explicitly initialize it to zero:
vector *vectorInit(int size)
{
vector *newVec = malloc(sizeof(vector));
if(!newVec)
{
printf("No memory!\n");
return NULL;
}
newVec->size = size;
newVec->array = malloc(size * sizeof(int));
newVec->alreadyIn = 0; // Remember to set this to zero
return newVec;
}
This problem should have been easy to detect in the debugger.
Also note that I removed the casts from malloc. One should not cast the result of malloc, or really any function returning void *.
I've written a piece of code but I'm not sure about how it works.
I want to create an array of pointers and pass it as argument to a function, like the following:
int main()
{
int *array[10] = {0};
for(int i = 0; i < 3; i++)
{
array[i] = (int *)malloc(3*sizeof(int *));
}
testFunction(array);
for(int i = 0; i < 3; i++)
{
free(array[i]);
}
return 0;
}
void testFunction(int *array[3])
{
//do something
return;
}
What I don't understand is the following. I declare array as an array of pointers, allocate memory to it by using malloc and then proceed to call testFunction. I want to pass the array by reference, and I understand that when I call the function by using testFunction(array), the array decays to a pointer to its first element (which will be a pointer also). But why in the parameters list I have to write (int *array[3]) with * and not just (int array[3])?
A parameter of type * can accept an argument of type [], but not anything in type.
If you write void testFunction(int arg[3]) it's fine, but you won't be able to access array[1] and array[2] and so on, only the first 3 elements of where array[0] points to. Also a comversion is required (call with testFunction((int*)array);.
As a good practice, it's necessary to make the function parametera consistent with what's passed as arguments. So int *array[10] can be passed to f(int **arg) or f(int *arg[]), but neither f(int *arg) nor f(int arg[]).
void testFunction(int **array, int int_arr_size, int size_of_array_of_pointers)
{
for(int j = 0; j < size_of_array_of_pointers; j++)
{
int *arrptr = array[j]; // this pointer only to understand the idea.
for(int i = 0; i < int_arr_size; i++)
{
arrptr[i] = i + 1;
}
}
}
and
int main()
{
int *array[10];
for(int i = 0; i < sizeof(array) / sizeof(int *); i++)
{
array[i] = malloc(3*sizeof(int));
}
testFunction(array, 3, sizeof(array) / sizeof(int *));
for(int i = 0; i < sizeof(array) / sizeof(int *); i++)
{
free(array[i]);
}
return 0;
}
Evering depends on what // do something means in your case.
Let's start from simple : perhaps, you need just array of integers
If your function change only values in array but does not change size, you can pass it as int *array or int array[3].
int *array[3] allows to work only with arrays of size 3, but if you can works with any arrays of int option int *array require additional argument int size:
void testFunction(int *array, int arr_size)
{
int i;
for(i = 0; i < arr_size; i++)
{
array[i] = i + 1;
}
return;
}
Next : if array of pointers are needed
Argument should be int *array[3] or better int **array (pointer to pointer).
Looking at the initialization loop (I changed sizeof(int *) to sizeof(int))
for(int i = 0; i < 3; i++)
{
array[i] = (int *)malloc(3*sizeof(int));
}
I suppose you need 2-dimension array, so you can pass int **array but with sizes of two dimensions or one size for case of square matrix (height equal to width):
void testFunction(int **array, int wSize, int hSize)
{
int row, col;
for(row = 0; row < hSize; row++)
{
for(col = 0; col < wSize; col++)
{
array[row][col] = row * col;
}
}
}
And finally : memory allocation for 2D-array
Consider the following variant of your main:
int main()
{
int **array;
// allocate memory for 3 pointers int*
array = (int *)malloc(3*sizeof(int *));
if(array == NULL)
return 1; // stop the program
// then init these 3 pointers with addreses for 3 int
for(int i = 0; i < 3; i++)
{
array[i] = (int *)malloc(3*sizeof(int));
if(array[i] == NULL) return 1;
}
testFunction(array, 3, 3);
// First, free memory allocated for int
for(int i = 0; i < 3; i++)
{
free(array[i]);
}
// then free memory allocated for pointers
free(array);
return 0;
}
Pay attention, that value returned by malloc should be checked before usage (NULL means memory was not allocated).
For the same reasons check can be added inside function:
void testFunction(int **array, int wSize, int hSize)
{
int row, col;
if(array == NULL) // check here
return;
for(row = 0; row < hSize; row++)
{
if(array[row] == NULL) // and here
return;
for(col = 0; col < wSize; col++)
{
array[row][col] = row * col;
}
}
}
Currently I am trying to fill an array of size num with random values. To do this, I need to create two functions:
1: Write a function (*createdata) that allocates a dynamic array of num double values, initialising the values to 0.0.
2: Write a different function (gendata) that will populate an array of double values with random values generated using the rand() function.
Here is my attempt at writing how the functions operate (outside main() ):
double *createdata(int num)
{
int i = 0;
double *ptr;
ptr = (double *)malloc(sizeof(double)*num);
if(ptr != NULL)
{
for(i = 0; i < num; i++)
{
ptr[i] = 0.0;
}
}
}
double gendata(int num)
{
createdata(num);
int j = 0;
for(j = 0; j < num; j++)
{
ptr[j] = rand();
}
}
However, I know that there is something certainly wrong with the above.
What I would like is that once I have called both functions in main, I will have generated an array of size num that is filled with random numbers.
You have to pass the allocated pointer to the gendata function, because in it's current form, ptr is unknown. Does that even compile?
Example:
double *createdata(int num)
{
int i = 0;
double *ptr;
ptr = (double *)malloc(sizeof(double)*num);
if(ptr != NULL)
{
for(i = 0; i < num; i++)
{
ptr[i] = 0.0;
}
}
return ptr;
}
And:
double gendata(int num)
{
double *ptr = createdata(num);
int j = 0;
if(ptr != NULL)
{
for(j = 0; j < num; j++)
{
ptr[j] = rand();
}
}
}
Also note I'm checking for return NULL again from malloc.
Other hints others might say here:
Don't cast the return of malloc.
Don't forget to free the pointer after you use it entirely.
You're not returning anything in your function gendata, but you declared it as double. Use void instead if you're not going to return anything.
But you're probably gonna need to return the pointer from it anyways, so that you can use it later in other functions, such as main.
EDIT: So, this would be like this, as an example:
double *gendata(int num)
{
double *ptr = createdata(num);
int j = 0;
if(ptr != NULL)
{
for(j = 0; j < num; j++)
{
ptr[j] = rand();
}
}
return ptr;
}
And in your main:
int main(void)
{
double *data;
data = gendata(100);
printf("%g\n", data[5]);
// When you're done, call free
free(data);
return 0;
}
You need to return the array allocated in the createdata() function, otherwise you can't use it in gendata(), or anywhere else.
I'm not sure why gendata() is declared as returning a double, either.
In createdata(), you forgot to actually return the pointer to the newly allocated array at the end:
return ptr;
Also, your gendata() function needs to work on an already existing array, not generate its own. You should add it as an argument. Also, it doesn't need to return anything. So:
void gendata(double ptr[], int num)
{
int j = 0;
if (ptr != NULL) {
for(j = 0; j < num; j++) {
ptr[j] = rand();
}
}
}
However, you can simplify the above and reduce the nesting level:
void gendata(double ptr[], int num)
{
int j = 0;
if (ptr == NULL)
return;
for(j = 0; j < num; j++) {
ptr[j] = rand();
}
}
Note that double ptr[] actually means the same as double* ptr, but the [] syntax makes it more apparent that what the function wants is a pointer to an array of doubles rather than a pointer to a single double.
So now in order to create an array and then randomize it, you would do:
double* array = createdata(N); // Create an array of N doubles.
gendata(array, N); // Randomize it.
Well, I'm not quite familiar with how malloc works, although it looks like that will work fine, so I can't evaluate that, but the only issues I can see here are this:
You aren't returning ptr in your createdata function. So when you try to access ptr in your gendata function, there is no ptr array in scope. That will give you an error. Also, gendata function does not even return anything.
Look at this code, this should work:
double *createdata(int num)
{
int i = 0;
double *ptr;
ptr = (double *)malloc(sizeof(double)*num);
if(ptr != NULL)
{
for(i = 0; i < num; i++)
{
ptr[i] = 0.0;
}
}
return ptr; // return the pointer
}
double *gendata(int num) // you forgot the '*' here
{
double *ptr = createdata(num);
int j = 0;
for(j = 0; j < num; j++)
{
ptr[j] = rand();
}
return ptr; // i added this so you obviously return the pointer
}
I believe this will work, here's an example of using it:
int main()
{
int c;
double *data = gendata(8);
for(c = 0; c < 8; c++)
{
printf("%f\n", data[c]);
}
}
Can someone wiser than I please explain to me why the following code segment faults? There is no problem allocating the memory by reference, but as soon as I try to assign anything or free by reference, segfault occurs.
I'm sure I'm missing some fundamental concept about pointers and passing by reference, hopefully some light can be shed.
#include <stdlib.h>
#include <stdio.h>
void allocateMatrix(float ***);
void fillMatrix(float ***);
void freeMatrix(float **);
int main() {
float **matrix;
allocateMatrix(&matrix); // this function calls and returns OK
fillMatrix(&matrix); // this function will segfault
freeMatrix(matrix); // this function will segfault
exit(0);
}
void allocateMatrix(float ***m) {
int i;
m = malloc(2*sizeof(float*));
for (i = 0; i < 2; i++) {
m[i] = malloc(2*sizeof(float));
}
return;
}
void fillMatrix(float ***m) {
int i,j;
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
(*m)[i][j] = 1.0; // SEGFAULT
}
}
return;
}
void freeMatrix(float **m) {
int i;
for (i = 0; i < 2; i++) {
free(m[i]); // SEGFAULT
}
free(m);
return;
}
One set of problems is here:
void allocateMatrix(float ***m) {
int i;
m = malloc(2*sizeof(float*));
for (i = 0; i < 2; i++) {
m[i] = malloc(2*sizeof(float));
}
return;
}
You need to assign to *m to get the information back to the calling code, and also you will need to allocate to (*m)[i] in the loop.
void allocateMatrix(float ***m)
{
*m = malloc(2*sizeof(float*));
for (int i = 0; i < 2; i++)
(*m)[i] = malloc(2*sizeof(float));
}
There's at least a chance that the other functions are OK. The fillMatrix() is written and invoked correctly, though it could be simplified by losing the third * from the pointer:
void fillMatrix(float **m)
{
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
m[i][j] = 1.0;
}
}
It might be advisable to pass the triple-pointer to freeMatrix() so that you can zero the pointer in the calling function:
void freeMatrix(float ***m)
{
for (int i = 0; i < 2; i++)
free((*m)[i]);
free(*m);
*m = 0;
}
Calling then becomes:
allocateMatrix(&matrix);
fillMatrix(matrix);
freeMatrix(&matrix);
Good use of indirection. Just try to be consistent with format. It improves readability and reduces errors. e.g.
function calls:
allocateMatrix &matrix
fillMatrix &matrix
freeMatrix &matrix
declarations
void allocateMatrix float ***m
void fillMatrix float ***m
void freeMatrix float ***m
handling
(*m)[i] = malloc(2 * sizeof(float))
(*m)[i][j] = 1.0
free (*m)[i]
Returning of pointer from your function is probably the better way to allocate memory:
float **allocateMatrix() {
int i;
float **m;
m = malloc(2*sizeof(float *));
for (i = 0; i < 2; i++) {
m[i] = malloc(2*sizeof(float));
}
return m;
}
int main() {
float **m;
m = allocateMatrix();
/* do other things
fillMatrix(matrix);
freeMatrix(&matrix);
*/
}