I am struggling really hard to understand this behavior so maybe someone can shed some light on the situation.
I simply can't figure out why I can't return a pointer to a struct from a method and expect to be able to still re-use it afterwards.
As you can see the generateSmallMatrix() method creates an int[] array and sets it inside the ysmf struct that I then return to main. Main then takes the ysmf* and calls printArray (again). And on the third try the array cannot be retrieved any more..
It's driving me crazy..
I have checked with my Eclipse debugger that on all calls the location of matrix->A is identical (0x7fffffffe180 - so for all I know about C pointers any form of accessing that int should return the correct value - be it *(ax++) or ax[i]) .. but neither do..
Very frustrating to say the least, so here is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct sparseMatrix
{
int* A;
} ysmf;
void printArray(int* ax, int length) {
int i = 0;
for (i = 0; i < length; i++) {
printf("%i,", ax[i]);
}
printf("\n");
}
ysmf* generateSmallMatrix()
{
ysmf *matrix = malloc(sizeof(ysmf));
int a[] = {1,2,3,9,1,4};
printArray(a, 6); // returns 1,2,3,9,1,4,
matrix->A = a;
printArray(matrix->A, 6); //returns 1,2,3,9,1,4,
//printArray(matrix->A, 6);
return matrix;
}
int main(void) {
ysmf* matrix = generateSmallMatrix();
printArray(matrix->A, 6); //returns 1,6,-7856,32767,1,4,
return EXIT_SUCCESS;
}
You can see the problem occuring where I have inserted the comments.
I know this is probably something totally basic I shouldn't have missed..
Because a is a local array, whose lifetime ends when the generateSmallMatrix() function ends. Accessing it after that results in undefined behaviour.
This line
ysmf *matrix = malloc(sizeof(ysmf));
Allocates only enough space for your ysmf struct, which in this case, is just an int pointer. So you then go and point that at 'a'.
matrix->A = a;
The problem is that a is on the stack. So it is now pointing at this memory address but when you exit the function that memory is no longer reserved for the array.
If you instead malloced memory for 'a' and pointed your struct at that, then you would be OK.
Try this...
ysmf* generateSmallMatrix()
{
ysmf *matrix = malloc(sizeof(ysmf));
int a[] = {1,2,3,9,1,4};
printArray(a, 6);
matrix->A = malloc(sizeof(int) * 6);
memcpy(matrix->A, a, sizeof(int) * 6);
printArray(matrix->A, 6);
return matrix;
}
Now outside of the generateSmallMatrix function you should be able to print the correct values. However, be sure to free what was malloc'd.
int main(void) {
ysmf* matrix = generateSmallMatrix();
printArray(matrix->A, 6);
free(matrix->A);
free(matrix);
return EXIT_SUCCESS;
}
Hope this helps.
Related
I want to make a function that returns an int array. However I am having difficulties as this attempt will return the same value for both out1 and out2
int * foo(int bar) {
static int fizz[2] = {0, 0};
fizz[0] = bar;
fizz[1] = bar + 1;
return fizz;
}
int main() {
int *out1 = foo(1);
int *out2 = foo(2);
printf("(%d, %d)\n(%d, %d)", out1[0], out1[1], out2[0], out2[1]);
}
Output:
(2, 3)
(2, 3)
And then this solution does not compile as I am returning the address of a local variable (which is what lead me to attempt the static keyword in the first place.
int * foo(int bar) {
int fizz[2] = malloc(2*sizeof(int));
fizz[0] = bar;
fizz[1] = bar + 1;
return fizz;
}
int main() {
int *out1 = foo(1);
int *out2 = foo(2);
printf("(%d, %d)\n(%d, %d)", out1[0], out1[1], out2[0], out2[1]);
}
So I know why this code is not working but I have no clue what other methods I could attempt to successfully write this function.
Your second attempt is close, and certainly along the right path. However, the return value from the malloc function is a pointer (not an array) and the fizz variable should be declared as such (a pointer-to-integer, or int*).
Your concern about this "returning the address of a local variable" is not relevant, in this case; what you are returning is the value of a local variable, which just happens to be an address. The value of that address, returned by malloc, will be copied to the value returned by the function.
Also, when using malloc , never forget to release the memory when you're finished with it, using the free function.
Here's a working code sample, which is changed very little from your second snippet:
#include <stdio.h>
#include <stdlib.h>
int* foo(int bar)
{
int *fizz = malloc(2 * sizeof(int)); // Save the allocated pointer (locally)...
fizz[0] = bar;
fizz[1] = bar + 1;
return fizz; // ... and return a COPY of the value of that address!
}
int main()
{
int* out1 = foo(1);
int* out2 = foo(2);
printf("(%d, %d)\n(%d, %d)", out1[0], out1[1], out2[0], out2[1]);
// Don't forget to free the allocated memory...
free(out1);
free(out2);
}
It's not entirely clear whether or not you understand why your first snippet gives the same values for both out1 and out2. So, just in case: the static int fizz[2] line declares a fixed block of memory – though it's only accessible, by name, from within that function. Each call to foo will return a pointer to that (same) memory, and the printf call will display the values assigned to its elements in the most recent (latest) update.
Your first code is also fine, only when to print the result....
int* foo(int bar) {
static int fizz[2]={0,0};
fizz[0] = bar;
fizz[1] = bar + 1;
return fizz;
}
int main() {
int* out1=foo(1);
printf("%d,%d\n", out1[0], out1[1]);
int* out2=foo(2);
printf("%d,%d \n", out2[0], out2[1]);
return 0 ;
}
gives the result :
1,2
2,3
This question already has answers here:
How do I modify a pointer that has been passed into a function in C?
(7 answers)
Closed 4 years ago.
I'm trying to create an array of a structure in an external function "add", and print it's fields, but when I get back to the main function "arr" it is still NULL.
I'm confused because I've been creating arrays in external functions many times and it worked.. probably this time the dynamic memory allocation is messing the things up. Can I please get an advice on this matter?
Thanks!
typedef struct {
char* id;
char gender;
char *name;
}Member;
void add(Member arr[], int size);
void print(Member arr[], int *size);
int main()
{
char temp[100];
int size=0;
Member *arr = NULL;
Member *data = (Member*)malloc(sizeof(Member));
//scan fields
gets(temp);
data->id = (char*)malloc((strlen(temp) + 1) * sizeof(char));
strcpy(data->id, temp);
gets(temp);
data->gender = temp;
gets(temp);
data->name = (char*)malloc((strlen(temp) + 1) * sizeof(char));
strcpy(data->name, temp);
add(data, &arr, &size);
print(arr, &size);
return 0;
}
void add(Member *data, Member arr[], int *size)
{
arr = (Member*)realloc(arr, (*size + 1) * sizeof(Member));
arr[*size] = *data;
}
void print(Member arr[], int *size)
{
for (int i = 0;i < *size;i++)
{
puts(arr->id);
puts(arr->gender);
puts(arr->name);
}
}
Imagine code like this:
#include <stdio.h>
void f(int i){
i++;
}
int main(){
int i = 3;
f(3);
printf("%d\n", i);
}
We all know that f() incremented its local copy of i, not the variable that was passed into f() to initially set that value. With that having been said, let's take another look at your add():
void add(Member *data, Member arr[], int *size)
{
arr = (Member*)realloc(arr, (*size + 1) * sizeof(Member));
arr[*size] = *data;
}
When arr is passed into the function, it contains a memory address of the current arr, which starts as NULL. But just like when we change the local value of i in f() above, setting arr to a new value within add() only changes the local value; it does not change main()'s arr.
We also know that if we pass a function an address of data we want it to change, the function can then change the data at that address and the data at that address will reflect the change in the calling function:
#include <stdio.h>
void f(int * i){
*i = *i + 1;
}
int main(){
int i = 3;
f(&i);
printf("%d\n", i);
}
The same logic applies ( though it gets more confusing) when you want to change a pointer's value; send that pointer's address! Let's start with a very simple case:
#include <stdio.h>
#include <stdlib.h>
void f(int** i){
*i = (int*)malloc(sizeof(int));
**i = 99;
}
int main(){
int *i = NULL;
f(&i);
printf("%d\n", *i);
}
Here we create a pointer to an int in main, and initialize it to NULL. Then we send the address of that pointer (that is, the address we stored the NULL) to f(), which (like in your program) allocates some memory and puts the address of the newly allocated pointer _at the address of main's i. Now, the data stored at &i has changed, and dereferencing i from main() will dereference the newly allocated address.
In your code, just as in mine, you'll have to change the way you're passing arr to add() as well as how you interact with it - an exercise you'll get the most out of thinking through yourself. But in short, something like this should get you started:
pass add arr's address, not the address it stores.
Store new address of reallocated memory back to the same address, that is, &arr
make sure to update add() to dereference the pointer to a pointer twice to set the member at the address stored at the address &arr.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int* create_int_array(){
int* arr;
arr = (int *)calloc(1,sizeof(int));
return arr;
}
char** create_string_array(){
char** arr = calloc(1,sizeof(char));
return arr;
}
void append_int(int* array, int element, int index){
array = (array+index);
*array = element;
}
void append_string(char** array , char* element,int index){
*(array + index) = calloc(1,sizeof(char*));
strcpy(*(array + index),element);
}
void delete_string(char** array, int index){
free(array[index]);
}
void delete_int(int* array,int index){
array[index] = NULL;
}
/////// M A I N F I L E ///////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "basic_data_file.h"
int main(int argc, char const *argv[])
{
/* code */
char **array;
array = create_string_array();
char *full_name = calloc(strlen("hamza arslan"),sizeof(char*));
strcpy(full_name,"hamza arslan");
char* mail = calloc(strlen("test#gmail.com"),sizeof(char*));
strcpy(mail,"test#gmail.com");
char* address = calloc(strlen("Hacettepe Universty"),sizeof(char*));
strcpy(address,"Hacettepe Universty");
char* statu = calloc(strlen("student"),sizeof(char*));
strcpy(statu,"student");
append_string(array,full_name,0);
append_string(array,mail,1);
append_string(array,address,2);
append_string(array,statu,4);
for(int i=0; i< 3; i++){
printf("%s\n",array[i]);
free(array[i]); // get free double pointer
}
printf("%s\n",array[4]); // because index 3 blow up
free(full_name);
free(mail);
free(address);
free(statu);
return 0;
}
I was try to own my basic array library . As you know else in some languages have high level array types. They are making easy our stocking operation. But in c, it's more complicated especially about string. I have 2 problem in here . First of all , when i give index=3 in append_string function , code blow up with Aborted(core dumped) error.(./run': double free or corruption (out)). Secondly , when i was checking leak memory ,it's get memory leak even i use free. What can i do?
Your create_xy_array functions allocate an array of 1 element, and they stay that way until the very end. When you have a one-element array and index, read/write its second and further elements, C itself happily approves, but the result will not work, it silently destroys everything in its path.
First of all, for having a dynamic array, you have to track its length yourself, C allocations/arrays do not know their own size. So you need a struct, containing the length and a pointer, something like
typedef struct IntArray {
int length;
int *elements;
} IntArray;
Then allocate it, for 0 elements, as there is nothing inside at the beginning:
IntArray* create_int_array() {
IntArray* ret = (IntArray*) malloc(sizeof(IntArray));
ret->length = 0;
ret->elements = NULL;
return ret;
}
void free_int_array(IntArray* arr) {
free(arr->elements);
free(arr);
}
Then you can try putting something inside:
void append_int(IntArray* arr, int element) {
arr->length++;
arr->elements = (int*) realloc(arr->elements, arr->length*sizeof(int));
arr->elements[length-1] = element;
}
(appending means adding something to the end of an array, there is no need for indices here)
And this could go on forever, deletion of an arbitrary element should shift the "upper" part of the array (memcpy) and resize the result to one element smaller or you could track the capacity of the array, which can be larger than its current length (but then it has to be incorporated into the append function and probably others).
(Disclaimer: I hope the snippet is correct, but I do not use C too often - and I can not suggest a good tutorial for the same reason, but that is what you probably need)
Note: I haven't code in C for years and I haven't check the code so double check and let me know.
Based on your description, you are trying to do a Vector.
Therefore, there are different ways that you can handle this.
Approach 1:
Create a structure which will hold the array, the capacity of the array, and the size of the array.
typedef struct StrArray{
int capacity;
int size;
int *integers;
}
The trick here is to take attention when you increase/decrease the capacity.
If you increase the capacity above the size of the array, then:
You need to create a new array with double the capacity
Copy all elements to the new array
Change pointer to new array
Free the memory of the old array
Approach 2
You can extend the previous approach by creating a function which returns a struct which holds the storage plus function pointers to the methods you wish to implement.
typedef struct StrStorage{
int capacity;
int size;
int *integers;
} StrStorage;
typedef struct StrArray {
StrStorage storage;
int (*capacity)(StrArray*);
int (*size)(StrArray*);
StrArray *(*append)(StrArray*, int);
void (*increaseStorage)(StrArray*);
// Add other methods here
} StrArray;
int capacity(StrArray *self) {
return self->storage->capacity;
}
int size(StrArray *self) {
return self->storage->size;
}
StrArray *append(StrArray *self, int integer){
if ((self->capacity() + 1) > self->size()){
self->increaseStorage();
}
// The rest of the magic goes here
return self;
}
StrArray *initializeStrArray(int n) {
StrArray* strArray = malloc(sizeof(StrArray));
strArray->chars = malloc(sizeof(char) * n);
strArray->capacity= capacity;
strArray->append = append;
return strArray;
}
Approach 3:
This approach is a continuation of the previous one.
In order to reduce the memory allocation, you can create an equivalent to a singleton which holds all the manipulation functions and then assi
There will be several crashes, but here is one:
char** arr = calloc(1,sizeof(char));
You are allocating 1 byte which is not sufficient to store a (char *), which needs between 2 and 8 bytes depending on the OS and target machine.
Try this instead:
char** arr = calloc(1,sizeof(char*));
You should double-check each line of code. C is not a forgiving language - mistakes are severely punished.
I am trying to have dynamically allocate arrays of structures and perform operations on them but i keep running into segmentation faults. could someone help me out?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *malloc(size_t size);
typedef struct {
double x;
double y;
} coords;
struct figure {
char fig_name[128];
int coordcount, size_tracker;
coords *pointer;
} fig;
void init_fig(int n, struct figure **point)
{
printf("%u\n", sizeof(coords));
point[n]->pointer = malloc(sizeof(coords) * 20); <-------SEGFAULT
if (point[n]->pointer == NULL){
exit(-1);
}
point[n]->pointer[19].x = 2;
point[n]->pointer[0].x = 1;
point[n]->pointer[0].y = 2;
point[n]->pointer[7].x = 100;
}
int main()
{
int numfigs = 1;
struct figure * point;
point = malloc(sizeof(struct figure) * 16);
point = &fig;
point[1].coordcount = 1;
init_fig(numfigs, &point);
return 0;
}
I labelled where the first seg fault occurs, (used ddd). what i dont get is that i can manipulate point[1] in main but not in any other function.
I agree with #Maxim Skurydin.
Nevertheless I'd like to explain your mistake in some more details.
Reading your init_fig one assumes that the parameter you pass struct figure **point - is actually array of pointers to struct figure. And this function accesses its n'th element.
However in your main you do something else. You allocate an array of struct figure, and your point variable points to its head. Then you take the address of this local variable and call your init_fig.
Here's the problem. init_fig assumes that you pass it an array of pointers, whereas actually this "array" consists of a single element only: the local point variable declared in main.
EDIT:
How to do this properly.
Leave main intact, fix init_fig.
This means that actually there's an array of figure structs. Means - a single memory block, interpreted as an array of consequent structs.
void init_fig(int n, struct figure *point)
{
printf("%u\n", sizeof(coords));
point[n].pointer = malloc(sizeof(coords) * 20); <-------SEGFAULT
if (point[n].pointer == NULL){
exit(-1);
}
point[n].pointer[19].x = 2;
point[n].pointer[0].x = 1;
point[n].pointer[0].y = 2;
point[n].pointer[7].x = 100;
}
Leave init_fig intact. Fix main.
This means that we actually should allocate an array of pointers, every such a pointer should point to an allocated point structure.
int main()
{
int numfigs = 1;
struct figure ** point;
point = malloc(sizeof(struct figure*) * 16);
for (i = 0; i < 16; i++)
point[i] = malloc(sizeof(struct figure));
point[1].coordcount = 1;
init_fig(numfigs, &point);
return 0;
}
You allocate memory and store the pointer in point but then you forget that pointer when you assign &fig to it.
point = malloc(sizeof(struct figure) * 16);
point = &fig;
So, you are essentially trying to write fig[1], that does not make sense.
struct figure * point;
point = malloc(sizeof(struct figure) * 16);
here point is pointer pointing to memory of 16 structures in heap
but in the next line you have done this
point = &fig;
so its memory leak and also point is not pointing to that allocated region anymore
and also init_fig should be like this
void init_fig(int n, struct figure **point)
It's the problem of segfault
Eliminate this line point = &fig;
and modify the function:
void init_fig(int n, struct figure *point)
{
...
point[n].pointer = (coords*) malloc(sizeof(coords) * 20);
...
}
since you should pass an array of structs and not an array of pointers.
Also, add a third parameter to the init_fig function so you can pass the size of the array of points that you want to create. Like :
void init_fig(int n, struct figure *point, int size)
{
...
point[n].pointer = (coords*) malloc(sizeof(coords) * size);
...
}
Therefore, making the function more reusable.
Modify also the call to that function:
init_fig(numfigs, &point); to init_fig(numfigs, point);
How to return 1000 variables from a function in C?
This is an interview question asked which I was unable to answer.
I guess with the help of pointers we can do that. I am new to pointers and C can anyone give me solution to solve this problem either using pointers or different approach?
Pack them all in a structure and return the structure.
struct YourStructure
{
int a1;
int b2;
int z1000;
};
YouStructure doSomething();
If it's 1000 times the same type (e.g. int's):
void myfunc(int** out){
int i = 0;
*out = malloc(1000*sizeof(int));
for(i = 0; i < 1000; i++){
(*out)[i] = i;
}
}
This function allocates memory for 1000 integers (an array of integers) and fills the array.
The function would be called that way:
int* outArr = 0;
myfunc(&outArr);
The memory held by outArr must be freed after use:
free(outArr);
See it running on ideone: http://ideone.com/u8NX5
Alternate solution: instead of having myfunc allocate the memory for the integer array, let the caller do the work and pass the array size into the function:
void myfunc2(int* out, int len){
int i = 0;
for(i = 0; i < len; i++){
out[i] = i;
}
}
Then, it's called that way:
int* outArr = malloc(1000*sizeof(int));
myfunc2(outArr, 1000);
Again, the memory of outArr must be freed by the caller.
Third approach: static memory. Call myfunc2 with static memory:
int outArr[1000];
myfunc2(outArr, 1000);
In that case, no memory has to be allocated or freed.
Array Pointer approach:
int * output(int input)
{
int *temp=malloc(sizeof(int)*1000);
// do your work with 1000 integers
//...
//...
//...
//ok. finished work with these integers
return temp;
}
Struct pointer approach:
struct my_struct
{
int a;
int b;
double x;
...
//1000 different things here
struct another_struct;
}parameter;
my_struct * output(my_struct what_ever_input_is)
{
my_struct *temp=malloc(sizeof(my_struct));
//...
//...
return temp;
}
This is how you do it in C.
void func (Type* ptr);
/*
Function documentation.
Bla bla bla...
Parameters
ptr Points to a variable of 'Type' allocated by the caller.
It will contain the result of...
*/
If your intention wasn't to return anything through "ptr", you would have written
void func (const Type* ptr);
instead.