I create a 2-D array using malloc. When I use printf to print the array element in for loop, everything is fine. But when I want to use printf in main, these is a Segmentation fault: 11.
Could you please tell me what the problem with the following code is?
#include <stdlib.h>
#include <stdio.h>
void initCache(int **cache, int s, int E){
int i, j;
/* allocate memory to cache */
cache = (int **)malloc(s * sizeof(int *)); //set
for (i = 0; i < s; i++){
cache[i] = (int *)malloc(E * sizeof(int)); //int
for(j = 0; j < E; j++){
cache[i][j] = i + j;
printf("%d\n", cache[i][j]);
}
}
}
main()
{
int **c;
initCache (c, 2, 2);
printf("%d\n", c[1][1]); // <<<<<<<<<< here
}
Since your cache is a 2D array, it's int**. To set it in a function, pass int***, not int**. Otherwise, changes to cache made inside initCache have no effect on the value of c from main().
void initCache(int ***cache, int s, int E) {
int i, j;
/* allocate memory to cache */
*cache = (int **)malloc(s * sizeof(int *)); //set
for (i = 0; i < s; i++) {
(*cache)[i] = (int *)malloc(E * sizeof(int)); //int
for(j = 0; j < E; j++){
(*cache)[i][j] = i + j;
printf("%d\n", (*cache)[i][j]);
}
}
}
Now you can call it like this:
initCache (&c, 2, 2);
You changed a local variable, which won't effect the local variable c in main.
If you want to allocate in the function, why pass a variable? Return it from the function.
int **c = initCache(2, 2);
You could use a return, or else a *** as suggested by others. I'll describe the return method here.
initCache is creating and initializing a suitable array, but it is not returning it. cache is a local variable pointing to the data. There are two ways to make this information available to the calling function. Either return it, or pass in an int*** and use that to record the pointer value.
I suggest this:
int** initCache(int **cache, int s, int E){
....
return cache;
}
main()
{
int **c;
c = initCache (2, 2);
printf("%d\n", c[1][1]); <<<<<<<<<< here
}
====
Finally, it's very important to get in the habit of checking for errors. For example, malloc will return NULL if it has run out of memory. Also, you might accidentally as for a negative amount of memory (if s is negative). Therefore I would do:
cache = (int **)malloc(s * sizeof(int *));
assert(cache);
This will end the program if the malloc fails, and tell you what line has failed. Some people (including me!) would disapprove slightly of using assert like this. But we'd all agree it's better than having no error checking whatsoever!
You might need to #include <assert.h> to make this work.
Related
I've a problem about deallocating memory using free() in C.
My program generates a random genealogic tree using a matrix. This matrix can be very huge depending on the number of family members. The program seemed to work fine until I decided to generate more than one tree. I noticed that generating about 100 trees causes my 8GB RAM to fill! I'm sure I can make a better code to reduce the demand of memory, but my problem remains.
I use free() to deallocate memory and there's no error. I installed Valgrind to se what's happening and it says that about 100 million byte per tree are definitely lost. This means that free() doesn't work fine. I don't now where is the problem. I link some functions that I think are correlated to the problem.
typedef struct{
int f_id;
char f_name[L_NAMES];
int generations;
int n_members;
type_people *members;
int_mtx *mtx;
}type_family;
The struct above is for the family.
typedef struct temp{
int p_id;
char name[L_NAMES];
char f_name[L_NAMES];
int generation;
int n_sons;
struct temp **sons;
int f_id;
int sex;
int age;
}type_people;
This is for the members.
typedef struct{
int i;
int j;
int **val;
}int_mtx;
And the matrix.
In the main i call the function to initialize the tree:
type_family *family_a;
family_a = malloc(sizeof(type_family));
family_a = init_family_n_gen(family_a, 6);
This is the frist part of init_family_n_gen():
type_family *init_family_n_gen(type_family *family, int n){
...
family->members = malloc(max_people * sizeof(type_people));
family->mtx = mtxcalloc(family->mtx, max_people, max_people - 1);
...
This code is for mtxcalloc that initializes the matrix:
int_mtx *mtxcalloc(int_mtx *mtx, int i, int j){
mtx = malloc(sizeof(int_mtx));
mtx->i = i;
mtx->j = j;
mtx->val = malloc(i * sizeof(int *));
for(int a = 0; a < i; a++){
mtx->val[a] = malloc(j * sizeof(int));
for(int b = 0; b < j; b++){
mtx->val[a][b] = 0;
}
}
return mtx;
}
And to conclude the code to deallocate the family:
void free_family(type_family *family){
for(int m = 0; m < family->n_members; m++){
if(family->members[m].n_sons != 0){
free(family->members[m].sons);
}
}
mtxfree(family->mtx);
free(family->members);
}
And the one to deallocate the matrix:
void mtxfree(int_mtx *mtx){
for(int i = 0; i < mtx->i; i++){
free(mtx->val[i]);
}
free(mtx->val);
free(mtx);
}
Screen capture of Valgrind output
So I call the free_family(family_a) every time i need to regenerate the family but the memory still increases. (In the photo above the number of byte become 1 billion if i regenerate the family for 50 times).
Thanks for the support!
EDITED
I made a minimal reproducible example that emulates my original code. The structs and variables are the same but I changed the functions according to Weather Vane: they are all void and I pass them the double **.
The init_family_n_gen becomes:
void init_family(type_family **f){
type_family *family = malloc(sizeof(type_family));
family->members = malloc(100 * sizeof(type_people));
for(int m = 0; m < 100; m++){
family->members[m].n_sons = 0;
}
mtxcalloc(&family->mtx, 100, 99);
family->mtx->val[0][1] = 7;
family->mtx->val[9][8] = 1;
mtxrealloc(&family->mtx, 5, 4);
*f = family;
}
The main is:
type_family *family_a;
init_family(&family_a);
free_family(&family_a);
The only thing I added is this function(Is the code right?):
void mtxrealloc(int_mtx **mtx, int i, int j){
(*mtx)->i = i;
(*mtx)->j = j;
(*mtx)->val = realloc((*mtx)->val, (*mtx)->i * sizeof(int *));
for(int a = 0; a < (*mtx)->i; a++){
(*mtx)->val[a] = realloc((*mtx)->val[a], (*mtx)->j * sizeof(int));
}
}
I noticed that the problem occours when i use the realloc function and i can't figure why. I link the images of Valgrind with and without the function mtxrealloc. (I see that there is aslo a 48 byte leak...).
Valgrind with realloc
Valgrind without realloc
Thanks again for your support!
This:
init_family(&family_a);
Causes this code from mtxcalloc to execute:
mtx->val = malloc(i * sizeof(int *));
for(int a = 0; a < i; a++){
mtx->val[a] = malloc(j * sizeof(int));
for(int b = 0; b < j; b++){
mtx->val[a][b] = 0;
}
}
, with i, j = 100, 99. That is, you allocate space for 100 pointers, and for each one, you allocate space for 99 ints. These are then accessible via family_a->mtx.
Very shortly thereafter, you make this call:
mtxrealloc(&family->mtx, 5, 4);
, which does this, among other things:
(*mtx)->val = realloc((*mtx)->val, (*mtx)->i * sizeof(int *));
That loses all the pointers (*mtx)->val[5] through (*mtx)->val[99], each of which is the sole pointer to allocated space sufficient for 99 ints. Overall, sufficient space for 9405 ints is leaked before you even perform any computations with the object you are preparing.
It is unclear why you overallocate, just to immediately (attempt to) free the excess, but perhaps that's an artifact of your code simplification. It would be much better to come up with a way to determine how much space you need in advance, and then allocate only that much in the first place. But if you do need to reallocate this particular data, then you need to first free each of the (*mtx)->val[x] that will be lost. Of course, if you were going to reallocate larger, then you would need to allocate / reallocate all of the (*mtx)->val[x].
I use nested data structure for fibonacci, but I have a segmentation fault 11.
void fib(int **fib_array, int n){
fib_array = malloc(n * sizeof(int*));
for(int i = 0; i < n; i++){
fib_array[i] = malloc(sizeof(int));
}
for(int i = 0; i < n; i++){
if (i <= 1){
fib_array[i][0] = i;
}
else{
fib_array[i][0] = fib_array[i - 2][0] + fib_array[i - 1][0];
}
}
}
int main(int argc, char **argv) {
/* do not change this main function */
int count = strtol(argv[1], NULL, 10);
int *fib_sequence;
fib(&fib_sequence, count);
for (int i = 0; i < count; i++) {
printf("%d ", fib_sequence[i]);
}
free(fib_sequence);
return 0;
}
you are being too complicated. You just need a single malloc
*fib_array = malloc(n * sizeof(int));
and remove you second indexings [0] from everywhere
The consfusion comes from **int. This looks like a multi dim array. Its not - its declared ** so that you can set the value in the caller. A simpler exampe will help
void Make42(int* v)
{
*v = 42;
}
int main()
{
int myv = 0;
Make42(&myv);
// now myv == 42
}
The * in the arg list is so that Make42 can 'reach out' and modify what was passed to it (myv in this case)
In your code the ** on fib array is there for the same purpose. you could have done (In know you werent allowed to by the test definition )
int *fib(int n){
int *fib_array = malloc(n * sizeof(int));
......
return fib_array;
}
and in main
fib_sequence = fib(count);
this makes it much clearer that you are really manipulating a simple array
pm100 is right, but a little short for answering to a beginner...
At first, you have passed a pointer to a pointer. If you want the original pointer to contain a value, you need to dereference the pointer to pointer:
*fib_array = ...
By assigning to the pointer only (as you did in your code), you do not modify the orignial pointer (fib_sequence in main) at all. And as you have not initialised it, it might point to anywhere, thus the segmentation fault when you try to print the values of it.
Then why an array of pointers to individually stored values? You can use a contiguous array of ints, which you get by
*fib_array = malloc(n * sizeof(int));
OK, further usage won't be too nice ((*fib_array)[i] = ...), so I recommend a temporary variable instead:
int* fa = malloc(n * sizeof(int));
// now fill in the values comfortably:
fa[i] = ...;
// finally, assign the pointer to the target:
*fib_array = fa;
Side note: always check the result of malloc, it could be NULL:
fa = ...
if(fa)
// assign values
else
// appropriate error handling
In your concrete case, you could omit the else branch in your function and check your pointer outside within main function.
By the way, a simple return value would have made your live easier, too:
int* fib(int n)
{
int* fib_array = malloc(n * sizeof(int*));
// ...
return fib_array;
}
Notice: no need for pointer to pointer... Usage:
int* fib_sequence = fib(count);
I am trying to learn how to create a function that will take a dynamic int array (int arrayPtr = (int) malloc...) and replace it with another dynamic array. This new array will not simply be of different values, but potentially a different number of elements.
From my research, I've learned that I need to pass into this function a reference to my array pointer, rather than the pointer itself (&arrayPtr). That means the function signature needs to have int **arrayPtr instead of int *arrayPtr.
I feel like it makes sense to me; We need to tell arrayPtr to point to a different location in memory, so we need the memory address of arrayPtr rather than its value (the memory address of the original array);
I wrote a little test program to see if I understood, but I cannot get it to work. Using debugging, I've observed the following: From within the function, the (int **arrayPtr) doesn't represent the entire array, but just the first element. That is, I can get the value 500 if I do *arrayPtr[0], but *arrayPtr[1] is inaccessible memory.
Here is my test program:
#include <stdlib.h>
void replaceArray(int **arrayPtr, unsigned int arrayLength) {
int i;
int *tempArrayPtr;
tempArrayPtr = (int *)malloc(sizeof(int) * arrayLength);
for (i = 0; i < arrayLength; ++i) {
tempArrayPtr[i] = *arrayPtr[i] * 2;
}
free(arrayPtr);
arrayPtr = &tempArrayPtr;
return;
}
int main(int argc, char **argv) {
int i;
int arrayLength = 2;
int *arrayPtr;
arrayPtr = (int*)malloc(sizeof(int) * arrayLength);
for (i = 0; i < arrayLength; ++i) {
arrayPtr[i] = i + 500;
}
replaceArray(&arrayPtr, arrayLength);
exit(EXIT_SUCCESS);
}
The function is supposed create a new array with the value of each element of the original array doubled, and have the arrayPtr variable in the calling function refer to the new array instead. As i have written it, however, it gets SIGSEGV when the replaceArray function tries to access *arrayPtr[1].
I realize that this little demonstration program is not doing anything that requires the behavior that I'm testing. It is just so that I can understand the concept with a simple example.
Since this is a tiny, trivial, program, I feel justified in that the answer that I accept will contain the complete working version of this code.
There have to be three changes in you code:
void replaceArray(int **arrayPtr, unsigned int arrayLength) {
int i;
int *tempArrayPtr;
tempArrayPtr = malloc(sizeof(int) * arrayLength);
for (i = 0; i < arrayLength; ++i) {
tempArrayPtr[i] = (*arrayPtr)[i] * 2;//In this if you use the without braces it will acts array of pointers that is pointing to a array. So we have to get the value from that using that braces.
}
free(*arrayPtr);//<< here we have to free the memory of arrayPtr not the address of the &arrayPtr.
*arrayPtr = tempArrayPtr; // Here you have to assign the address to that value of arrayPtr.
return;
}
There is no need the type cast the return value of malloc.
Both of these lines are wrong:
free(arrayPtr);
arrayPtr = &tempArrayPtr;
The first line passes the address of your variable to free(), rather than the address of the actual allocated array. Since the variable is on the stack rather than mallocated, free() will crash or abort here. What you want to do instead is free(*arrayPtr):.
The second line merely sets the local variable arrayPtr to the address of the variable tempArrayPtr. What you want to do instead is *arrayPtr = tempArrayPtr;.
See the below code and the inline comments.
#include <stdlib.h>
void replaceArray(int **arrayPtr, unsigned int arrayLength) {
int i;
int *tempArrayPtr;
tempArrayPtr = malloc(sizeof(int) * arrayLength); //do not cast
for (i = 0; i < arrayLength; ++i) {
tempArrayPtr[i] = (*arrayPtr)[i] * 2;
}
free(*arrayPtr); // free the *arrayPtr, [which is `arrayPtr` from `main`]
*arrayPtr = tempArrayPtr; //copy tempArrayPtr and put it into *arrayPtr
return;
}
int main(int argc, char **argv) {
int i;
int arrayLength = 2;
int *arrayPtr;
arrayPtr = malloc(sizeof(int) * arrayLength); // do not cast
for (i = 0; i < arrayLength; ++i) {
arrayPtr[i] = i + 500;
}
replaceArray(&arrayPtr, arrayLength);
exit(EXIT_SUCCESS);
}
I tried different methods but eventually got errors. Please give a solution and a brief explanation of the concept.
uint8_t **subBytes()
{
int i,j;
uint8_t r,c;
uint8_t t[4][4];
for(i=0;i<4;i++)
{
for (j=0;j<4;j++)
{
r = pt[p1][j] & 0xf0;
r = r >> 4;
c = pt[p1][j] & 0x0f;
t[i][j] = (uint8_t *) malloc(sizeof(uint8_t));
t[i][j] = sBox[r][c];
}
p1++;
}
return t;
}
int main()
{
uint8_t **temp;
temp = subBytes();
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
printf("%x ", temp[i][j]);
}
printf("\n");
}
}
This is my original code. Here, I used malloc, but then too it is not working.
the memory space alloced for your matrix is a LOCAL VARIABLE.
The scope of a LOCAL VARIABLE is only within that function.
When you returned it is discarded.
In your code it is uint8_t t[4][4].
t is discarded right after return t.
So you return nothing and may cause undefined behavior.
You should use malloc to alloc memory for your matrix not just declare it locally.
in code
uint8_t **t.
t = malloc(sizeof(uint8_t) * 16 ) //size of a 4x4 matrix
then use t as a two dimension array and return t.like
t[0][0] = 1;
don't forgot to free it after use it out side of the function.
free(t);
m is LOCAL VARIABLES. When add returns, m is DESTROYED!
You SHOULD NOT return the pointer or reference of local variables. Look the following code:
int foo() { return 1; }
int *bar() { int i = 1; return &i; }
When I call foo(), it returns 1.
When I call bar(), it try to return the local variables, i's address. But when bar() returns, the i variable is DESTROYED! So the return pointer become trash pointer. (Sorry, I don't know how to say that term in English;)
You should use like that:
void bar(int *ret) { *ret = 1; }
int i;
bar(&i); /* now i is 1 */
or
int *bar()
{
int *p = (int *)malloc(sizeof(int));
*p = 1;
return p;
}
int *pi = bar();
/* now *pi is 1 */
...
free(pi); /* You MUST free pi. If not, memory lack is coming~ */
(I recommend first one. the second one require free and it can be mistaken.)
When a variable is declared (statically allocated) within a function, it is placed on what is called the stack, which is only local to that function. When the program leaves that function's scope, the variable is no longer guaranteed to be preserved, and so the pointer you return to it is essentially useless.
You have three options to fix your error:
Don't do it
Simply declare the array in the same function as you use it, don't bother with trying to return a pointer from another function.
Pass a pointer to a variable local to main
A pointer to a variable local to main will be valid until main returns, so you could do this:
void subBytes(uint8_t t[4][4]){
//perform initialization of matrix on passed variable
}
int main(){
uint8_t temp[4][4];
subBytes(&temp);
//...
}
Dynamic Allocation
This will probably give you more errors than it will solve in this case, but if you are heartset on returning a pointer to a matrix, you could malloc() the memory for the array and then return it, but you would have to free() it afterwards.
In C, there are several ways to dynamically allocate a 2D array. The first is to create it as a single array, and operate on the indices to treat it as 2D.
//...
int *arr = (int *)malloc(rows*cols*sizeof(int));
for (int i = 0; i<rows; i++){
for (int j = 0; j<height; j++){
arr[i*height + j] = i*j; //whatever
}
}
return arr; // type is int *
//...
Note that in this method, you cannot use array[i][j] syntax, because the compiler doesn't know the width and height.
The second way is to treat it as an array of arrays, so store an array of pointers to other arrays.
//...
int **arr = (int **)malloc(rows*sizeof(int *));
for (int i = 0; i<rows; i++){
arr[i] = (int *)malloc(cols*sizeof(int));
}
arr[i][j] = 86; //whatever
return arr; //type is int **
//...
For further information, see: Pointer to Local Variable
I'm writing a method that receives a number l and returns a vector of size l with random numbers. I have this code, but does not work
#include <time.h>
int makea (int z) {
int a1[z];
int i;
for (i = 0; i < tam; i++) {
a1[i]=srand(time(0));
}
return a1;
}
These are the errors that the compiler returns me
arrays1.c: In function 'makea':
arrays1.c:12: error: void value not ignored as it ought to be
arrays1.c:14: warning: return makes integer from pointer without a cast
arrays1.c:14: warning: function returns address of local variable
I think is a problem of pointers... but I'm not really sure
A few problems:
Your array is allocated on the stack, meaning that when your function exits, the memory you return will be invalid
In C, you cannot return an array from a function, it must first decay into a pointer.
So, to fix, use malloc and a pointer:
int *makea (int z) {
int *a1 = malloc(sizeof(int) * z);
int i;
srand(time(NULL));
for (i = 0; i < tam; i++) {
a1[i]= rand();
}
// remember to free a1 when you are done!
return a1;
}
Also note that using malloc can sometimes basically grant you the 'random number' scenario for free, negating the need to loop through the elements as the value returned from malloc is garbage (and thus random numbers).
However, also note that malloc is implementation-specific, meaning that an implementation could theoretically clear the memory for you before returning it.
Your best bet is:
Declare the array outside of the routine, and pass it in to initialize it:
void init_array (int a[], nelms)
Plan B is pass a pointer to a pointer, and have the routine allocate and initialize it
Like this:
void alloc_and_init_array (int **a_pp, int nelms)
{
*a_pp = malloc (sizeof (int) * nelms);
...
... or, equivalently ...
int *
alloc_and_init_array (int nelms)
{
int *a_p = malloc (sizeof (int) * nelms);
...
return a_p;
A local variable like your array is allocated on the stack. At function return it is removed from the stack, so the pointer you return points to an unallocated memory location.
You have to allocate the array with malloc() or pass an already existing array to the function.
#include <time.h>
int makea (int z) {
int *a1 = (int*)malloc(z*sizeof(int));
int i;
for (i = 0; i < tam; i++) {
a1[i]=srand(time(0));
}
return a1;
}
IMPORTANT: remember to free memory allocated somewhere outside, when you do not need it anymore.
Well, first off your function says that it returns an int, yet you want to return an array, so that is wrong. Of course, you can't return an array in C either...
Second, you will have to return a pointer. You cannot copy arrays via assignment or assign a new value to an array at all in C, so your function won't be very useful. Either return an int* or take an int** as an output argument and initialize it in your function.
Also, your array is locally allocated, so even if the compiler didn't complain you would be returning invalid memory.
int makea (int size, int **out_array) {
int *temp, i;
if(!out_array)
return 0;
temp = malloc(sizeof(int) * size);
if(!temp)
return 0;
srand(time(0));
for (i = 0; i < size; ++i)
temp[i] = rand();
*out_array = temp;
return 1;
}
int main() {
int *arr;
if(!makea(10, &arr)) {
printf("Failed to allocate array");
return -1;
}
return 0
}
Another note:
temp[i] = srand(time(0));
That is wrong. srand seeds the random number generator, but does not return a random number. You call srand to input the seed and then call rand to get a random number.