This question already has an answer here:
Pointer losing its value + execv compilation warning
(1 answer)
Closed 7 years ago.
I have started to work on a program which implements a structure called "PhoneBook" having two members: "length" and "allocatedSpace", both of type "unsigned int". The structure is dynamically allocated. The two members of the structure are assigned in an external function called "InitializePhoneBook". Now, when I try to print the values of the two members of the structure inside the "main" function I get a "Segmentation fault" error.
PhoneBook.h
#ifndef PHONEBOOK_H
#define PHONEBOOK_H
struct PhoneBook
{
unsigned int length;
unsigned int allocatedSpace;
};
void InitializePhoneBook(struct PhoneBook *phoneBook);
void ClearPhoneBook(struct PhoneBook *phoneBook);
#endif
PhoneBook.c
#include <stdlib.h>
#include "PhoneBook.h"
void InitializePhoneBook(struct PhoneBook *phoneBook)
{
phoneBook = malloc(sizeof(struct PhoneBook) * 1);
phoneBook->length = 0;
phoneBook->allocatedSpace = 1000;
}
void ClearPhoneBook(struct PhoneBook *phoneBook)
{
free(phoneBook);
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "PhoneBook.h"
int main(void)
{
struct PhoneBook *phoneBook;
InitializePhoneBook(phoneBook);
printf("%d %d\n", phoneBook->length, phoneBook->allocatedSpace);
ClearPhoneBook(phoneBook);
return 0;
}
Running "./a.out" with "gdb" I get:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400621 in main () at ./main.c:12
12 printf("%u %u\n", phoneBook->length, phoneBook->allocatedSpace);
When you do malloc in InitializePhoneBook():
phoneBook = malloc(sizeof(struct PhoneBook) * 1);
It doesn't modify the pointer in main because the pointer you assign is local the function. Pass a pointer to pointer or rewrite the function return the malloced pointer.
void InitializePhoneBook(struct PhoneBook **phoneBook)
{
*phoneBook = malloc(sizeof(struct PhoneBook) * 1);
(*phoneBook)->length = 0;
(*phoneBook)->allocatedSpace = 1000;
}
call in main():
InitializePhoneBook(&phoneBook);
and change the prototype:
void InitializePhoneBook(struct PhoneBook **phoneBook);
Other issues I noticed:
You should also check the result of malloc for failure.
Use %u format specifier to print unsigned ints.
C is pass by value. Which means that the parameters are copied when calling a function. Your function InitializePhoneBook() will copy the non-initialised pointer, will assign to that copy the return value of malloc() and then forget that value when leaving the function. Your caller will continue with the un-initialized original.
Your function InitializePhoneBook() can be changed in 2 ways:
struct PhoneBook *InitializePhoneBook(void)
{
struct phoneBook *pb = malloc(sizeof(struct PhoneBook) * 1);
pb->length = 0;
pb->allocatedSpace = 1000;
return pb;
}
or
void InitializePhoneBook(struct PhoneBook **pPhoneBook)
{
*pPhoneBook = malloc(sizeof(struct PhoneBook) * 1);
(*pPhoneBook)->length = 0;
(*pPhoneBook)->allocatedSpace = 1000;
}
the call in main would have to be changed
struct PhoneBook *phoneBook = InitializePhoneBook();
or
struct PhoneBook *phoneBook;
InitializePhoneBook(&phoneBook);
respectively.
The scope of the malloced pointer remains inside the InitializePhoneBook function.
For that you must return the pointer to the main so change the prototype to:
struct PhoneBook *InitializePhoneBook(struct PhoneBook *);
and the last statement of the above function should be:
return phoneBook;
and inside main call it this way:
phoneBook=InitializePhoneBook(phoneBook);
Related
This question already has answers here:
How to change value of variable passed as argument?
(4 answers)
Closed 5 years ago.
When designing a game entity system in C, I attempted an "equals-free" initialization approach. I was surprised to see a linter tell me there was a memory leak at the end of my init function, and that my variable ent was never initialized in the following code. It turned out to be right because I got a "bus error":
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} entity_t;
void entity_init(entity_t* ent, int _x, int _y)
{
ent = malloc(sizeof(*ent));
ent->x = _x;
ent->y = _y;
}
int main(void)
{
entity_t* ent;
entity_init(ent, 10, 24);
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
What I thought the above code would do, was take my empty ent pointer supplied as an argument, tell it to point to some newly allocated memory, and then fill in that memory and everything would be fine. I have no idea what it's really doing to cause a "bus error", am I missing something critical about pointers and malloc?
I vaguely remember seeing something very similar to this done before in some C code (equals-free struct initialization) and I would strongly prefer to use an equals-free initialization style similar to this (broken) code if such a thing is possible in C.
Move the malloc call outside the initialization function:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} entity_t;
void entity_init(entity_t* ent, int _x, int _y)
{
ent->x = _x;
ent->y = _y;
}
int main(void)
{
entity_t* ent;
if(NULL==(ent = malloc(sizeof(*ent))))
return 1;
entity_init(ent, 10, 24);
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
You're assigning the pointer to the allocated block to a local variable (ent). That can't affect the ent in main.
If you wanted to keep the malloc in entity_init, you should use a double pointer, but you should also change the signature to allow for a way to signal malloc failure from entity_init
int entity_init(entity_t **ent, int _x, int _y)
{
if(NULL==(*ent = malloc(sizeof(**ent))))
return -1;
(*ent)->x = _x;
(*ent)->y = _y;
}
int main(void)
{
entity_t* ent;
if(0>entity_init(&ent, 10, 24))
return 1;
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
A more usual pattern for this would be:
entity_t *entity_new(int _x, int _y)
{
entity_t *ent = malloc(sizeof(*ent));
if (NULL==ent)
return NULL;
ent->x = _x;
ent->y = _y;
return ent;
}
int main(void)
{
entity_t* ent;
if(NULL==(ent=entity_new(10,24)))
return 1;
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
If you must allocate within the entity_init() function, you need to either return a pointer to the allocation, or add a layer of indirection by making ent a pointer to pointer to entity_t. In the posted code, within entity_init() ent is a copy of the pointer which was passed to the function. Any changes made to this pointer, such as assigning the address of a memory allocation to the pointer, will not be visible from the calling function since this copy will cease to exist after the function returns.
Also, note that you need to check the value returned from malloc() to be sure that the allocation was successful. If successful, the function can continue with the initialization process; if not, ent can remain a null pointer, which should be checked in the calling function:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} entity_t;
void entity_init(entity_t **ent, int _x, int _y)
{
*ent = malloc(sizeof **ent);
if (*ent) {
(*ent)->x = _x;
(*ent)->y = _y;
}
}
int main(void)
{
entity_t *ent;
entity_init(&ent, 10, 24);
if (ent == NULL) {
fprintf(stderr, "Allocation failure in entity_init()\n");
exit(EXIT_FAILURE);
}
printf("Entity: x%d y%d\n", ent->x, ent->y);
return 0;
}
Program output:
Entity: x10 y24
Okay, so the problem concerns adding values through function to structure. Honestly, I couldn't solve the problem (spent a lot of time trying), so I am asking for your help. While executing the program, I get a segmentation fault. It occurs while using the variables from stack stos.
typedef struct e {
int zaglebienie[100];
char *nazwa_funkcji[100];
int poz;
} *stack;
void put_on_fun_stack(int par_level, char *funame, stack stos) {
int i = stos->poz;
stos->zaglebienie[i] = par_level;
char *funkcja = strdup(funame);
stos->nazwa_funkcji[i] = funkcja;
stos->poz++;
}
int main() {
char *p = "makro";
stack stos;
stos->zaglebienie[0] = 0;
put_on_fun_stack(1, p, stos);
return 0;
}
You're declaring a pointer to stack but you're not allocating any memory to it.
And as already mentioned in the comments, using typedef with with a pointer will unnecessarily complicate your life.
So I suggest you create the struct stack and then in main declare a pointer to stack and allocate memory for it, somewhat like this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct e {
int zaglebienie[100];
char *nazwa_funkcji[100];
int poz;
} stack;
void put_on_fun_stack(int par_level, char *funame, stack *stos)
{
int i = stos->poz;
stos->zaglebienie[i] = par_level;
char *funkcja = strdup(funame);
stos->nazwa_funkcji[i] = funkcja;
stos->poz++;
}
int main(void)
{
char *p = "makro";
// calloc to initialize stos variables to 0
stack *stos = calloc(sizeof(stack), 1);
printf("stos->poz before: %d\n", stos->poz);
put_on_fun_stack(1, p, stos);
printf("stos->poz after: %d\n", stos->poz);
printf("stos->nazwa_funkcji[0]: %s\n", stos->nazwa_funkcji[0]);
free(stos->nazwa_funkcji[0]);
free(stos);
return 0;
}
Output:
stos->poz before: 0
stos->poz after: 1
stos->nazwa_funkcji[0]: makro
After some research I didn't find a good way to implement the std::bind in C.
I build a small program that implements an equivalent of std::bind in C by hacking the stack.
There's two functions I will try to bind to function with pre-defined arguments.
My problem is this code is only working under Windows. Under Linux, this is a mess. I this the problem is my knowledge of the stack and the way that arguments are store in memory.
Thanks,
Please, find below the code I made:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
The two functions I want to bind :
void test1 (int nombre, char t, int nombre2)
{
printf ("test 1 : %d%c%d\n", nombre, t, nombre2);
}
void test2 (char t, int nombre, int nombre2)
{
printf ("test 2 : %c%d%d\n", t, nombre, nombre2);
}
Two struct that will store the argument of each function (order of fields is important).
typedef struct {
int nombre;
char t;
int nombre2;
} struct1;
typedef struct {
char t;
int nombre;
int nombre2;
} struct2;
This "fake" struct will be use to write on the stack by dereferencing a structvoid* variable.
// Size must be bigger than every struct*
typedef struct {
int i[10];
} structvoid;
The main function.
int main(int argc, char** argv) {
// Variables to store the two functions and their arguments.
void * functions[2];
structvoid * data[2];
void *func1 = (void *)&test1;
void *func2 = (void *)&test2;
void (*functionPtrc)(structurevoid);
// Definition of the argument of the first function test1
struct1 data1;
data1.nombre = 15;
data1.t = 'c';
data1.nombre2 = 30;
// and storing data.
void *datac = malloc (sizeof (structvoid));
memcpy(datac, &data1, sizeof (struct1));
data[0] = (structvoid*)datac;
functions[0] = func1;
// Same thing with function 2.
struct2 data2;
data2.t = 'a';
data2.nombre = 5;
data2.nombre2 = 10;
datac = malloc (sizeof (structvoid));
memcpy(datac, &data2, sizeof (struct2));
data[1] = (structvoid*)datac;
functions[1] = func2;
// Get the pointer to the first function (test1);
functionPtrc = functions[0];
// All the hack is here. By dereferencing the data, this will write on the stack all arguments need by the test1 function.
functionPtrc(*data[0]);
functionPtrc = functions[1];
functionPtrc(*data[1]);
// To check the result.
test1 (data1.nombre, data1.t, data1.nombre2);
test2 (data2.t, data2.nombre, data2.nombre2);
return 0;
}
EDIT
Here a new version of the program by calling function via the calling convention. I only wrote the new lines. The problem of this method is I can only store data inside a "void *" field. If I increase the size of structvoid, I got garbage behaviors.
// Structure that memories each argument
typedef struct {
void *i[1];
} structvoid;
int main(int argc, char** argv) {
// Variables to store the two functions and their arguments.
void * functions[2];
structvoid * data[2];
void *func1 = (void *)&test1;
// Let's start with a maximum of 5 arguments
void (*functionPtrc)(structurevoid, structurevoid, structurevoid, structurevoid, structurevoid);
// Definition of the argument of the first function test1
struct1 data1;
data1.nombre = 15;
data1.t = 'c';
data1.nombre2 = 30;
// and storing data.
structvoid *datac = malloc (sizeof (structvoid)*5);
memcpy(&datac[0], &data1.nombre, sizeof (data1.nombre));
memcpy(&datac[1], &data1.t, sizeof (data1.t));
memcpy(&datac[2], &data1.nombre2, sizeof (data1.nombre2));
data[0] = datac;
functions[0] = func1;
// Get the pointer to the first function (test1);
functionPtrc = functions[0];
// Call the function with the arguments. The unused argument will be ignored.
functionPtrc(data[0][0], data[0][1], data[0][2], data[0][3], data[0][4]);
}
I am trying to change my C functions of nested structures to operate on pointers instead of passing and making copies of the structures which are quite large in reality.
here is a simplified version of what I want to do passing the structures around....
struct InnerStruct
{
int int1;
int int2;
};
struct OuterStruct
{
struct innerStruct inner1;
int outerResult;
};
void main (void)
{
struct OuterStruct outer1;
outer1 = get_outer ();
}
struct OuterStruct get_outer (void)
{
struct OuterStruct thisOuter;
thisOuter.inner1 = get_inner (void);
thisOuter.outerResult = get_result (thisOuter.inner1);
return thisOuter;
}
struct InnerStruct get_inner (void)
{
struct InnerStruct thisInnner;
thisInner.int1 = 1;
thisInner.int2 = 2;
return thisInner;
}
int get_result (struct InnerStruct thisInner)
{
int thisResult;
thisResult = thisInner.int1 + thisInner.int2;
return thisResult;
}
but the structure is quite large in reality and this is a frequent operation, so I'd rather pass around the pointers. Just not sure how the syntax works for nested structures like this. Here is my attempt....
struct InnerStruct
{
int int1;
int int2;
};
struct OuterStruct
{
struct innerStruct inner1;
int outerResult;
};
void main (void)
{
struct OuterStruct outer1;
get_outer (&outer1);
}
void get_outer (struct OuterStruct *thisOuter)
{
get_inner (&(thisOuter->inner1));
thisOuter->outerResult = get_result (&(thisOuter->inner1));
}
void get_inner (struct InnerStruct *thisInner)
{
thisInner->int1 = 1;
thisInner->int2 = 2;
}
int get_result (struct OuterStruct *thisInner)
{
int thisResult;
thisResult = thisInner->int1 + thisInner->int2;
return thisResult;
}
You should really look up more about how pointers work. But here is some sample C++ code. Notice the "&" tells your compiler to "not send the struct itself" to the function but a pointer to it. Just a warning never return a reference to a variable (unless you know what you are doing).
#include <iostream>
struct MyStruct
{
int a;
int b;
};
using namespace std;
void printStruct(MyStruct * mypointer) {
cout << "MyStruct.a=" << mypointer->a << endl;
cout << "MyStruct.b=" << mypointer->b << endl;
}
int main()
{
MyStruct s;
s.a = 2;
s.b = 1;
printStruct(&s);
return 0;
}
This will illustrate an easy way to pass pointers to structs. It is a much more efficient way to pass data around, especially when, as you say, the data can get very large. This illustration uses a compound struct, (struct within struct) with an array and pointer declared to pass around. Comments in code explain things.
This will all build and run so you can experiment with it. i.e., follow the data along with execution.
Here is an easy way: (using my own structs)
typedef struct {
int alfha;
int beta;
} FIRST;
typedef struct {
char str1[10];
char str2[10];
FIRST first;
}SECOND; //creates a compound struct (struct within a struct, similar to your example)
SECOND second[5], *pSecond;//create an array of SECOND, and a SECOND *
SECOND * func(SECOND *a); //simple func() defined to illustrate struct pointer arguments and returns
int main(void)
{
pSecond = &second[0]; //initialize pSecond to point to first position of second[] (having fun now)
SECOND s[10], *pS; //local copy of SECOND to receive results from func
pS = &s[0];//just like above;
//At this point, you can pass pSecond as a pointer to struct (SECOND *)
strcpy(pSecond[0].str2, "hello");
pS = func(pSecond);
// printf("...", pS[0]...);//pseudo code - print contents of pS, which now contains any work done in func
return 0;
}
SECOND * func(SECOND *a) //inputs and outputs SECOND * (for illustration, i.e., the argument contains all
{ //information itself, not really necessary to return it also)
strcpy(a[0].str1, "a string");
return a;
}
Although there is not much going on in func(), when the pointer returns to main(), it contains both the value copied in main, and the value copied in fucn(), as shown here:
Results: (in code)
Contents in pSecond:
I'm wondering what happens to a struct member that is pointing to a non-dynamically allocated variable. So:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int value;
int *pointer;
} MyStruct;
int year = 1989;
int main (int argc, const char * argv[]) {
MyStruct *myStruct = (MyStruct *) malloc(sizeof(MyStruct));
myStruct->value = 100;
myStruct->pointer = &year;
year++;
printf("%d \n", *myStruct->pointer);
// what happens to the myStruct->pointer member when we free myStruct ?
free(myStruct);
return EXIT_SUCCESS;
}
I assume it's destroyed an no longer points to year correct? If that is the case, the same would be true if *pointer where pointing to a function right?
like this:
typedef struct {
int value;
void (*someFunc)();
} MyStruct;
Then later:
void sayHi(){
printf("hi");
}
...
myStruct->someFunc = sayHi;
No special cleanup needed except free() if our struct was created with malloc? Thanks for any insights anyone has.
If you didn't malloc (or calloc/strdup/realloc) it you don't need to free it. Nothing special is needed - the member variable just points at something, it doesn't logically "own" the pointed at memory.
Your year member variable will still exist and is perfectly valid after you free(myStruct) - myStruct->pointer will be invalid to use though