C free an instance, which is pointed by other pointers - c

I have the following C code. I have two pointers pointing to the same object.
It says double free error. Can someone help to see what the problem is? Thanks.
#include <stdlib.h>
#include <stdio.h>
typedef struct edge {
int head;
} edge_t;
typedef struct edge_list_t {
edge_t *edge;
} edge_list_t;
int main() {
edge_list_t *p1;
edge_list_t *p2;
edge_t *c;
p1 = malloc(sizeof(edge_list_t));
p2 = malloc(sizeof(edge_list_t));
c = malloc(sizeof(edge_t));
p1->edge = c;
p2->edge = c;
free(c);
if (p2->edge) {
printf("not freed\n");
free(p2->edge);
} else {c
printf("freed\n");
}
return 1;
}

p2->edge = c;
free(c);
if (p2->edge) {
printf("not freed\n");
free(p2->edge);
^ the last free is a double free. Remember that after the first free call, the value of c is an invalid value.

Here:
p2->edge = c;
free(c);
when you free c the value of c does not change and even if it did the value of p2->edge would stay the same. It would hold the original value of c of course.
So you always free both c and p2->edge which both hold the same value.
To avoid that set c to NULL if you called free() on it and later check if(c) ,which will return false and not free c again.
Note: free() does not change the pointer in any way. It trust you that the pointer points to correct memory that was before never free()d.

You shouldn't free c once you've transferred control of it to p1, and you should not have both p1 and p2 sharing a single edge pointer, and you should release p1 and p2 via a function that also releases the edge pointer. These observations lead to:
#include <stdio.h>
#include <stdlib.h>
typedef struct edge
{
int head;
} edge_t;
typedef struct edge_list_t
{
edge_t *edge;
} edge_list_t;
// Will acquire a loop when you have an actual list of edges
static void free_edge_list(edge_list_t *e)
{
free(e->edge);
free(e);
}
int main(void)
{
edge_list_t *p1;
edge_list_t *p2;
edge_t *c;
p1 = malloc(sizeof(edge_list_t));
p2 = malloc(sizeof(edge_list_t));
c = malloc(sizeof(edge_t));
p1->edge = c;
c = malloc(sizeof(edge_t));
p2->edge = c;
free_edge_list(p1);
free_edge_list(p2);
return 0;
}
In general, you should check that memory allocations succeed; this code (still) doesn't do that.

Related

Malloc within function not changing pointer value

So when I pass a data type like a struct to assign some memory to it I find that the pointer doesn't change within the main scope. This further becomes a problem when I try to free the memory but obviously if its using the original pointer it will be pointing at the stack address.
void allocate(int *value){
value = malloc(10 * sizeof(int));
}
int main(){
int val2;
allocate(&val2);
free(&val2);
return 0;
}
I can fix this by using a double pointer to be passed into the allocate function but some course work I'm doing requires to only pass a pointer and I cant get it to update the pointer when it returns to main. I have looked around for a while but cant find a straight forward answer, I feel like my coursework is wrong but that might be my lack of understanding.
The requirement to "only pass a pointer" seems contrived, and you could argue that a pointer to pointer (not a "double pointer") is a pointer, but perhaps you could use void * to punch a hole in the type system. Or use a struct:
#include <stdlib.h>
#include <stdio.h>
struct intbuffer {
int *d;
size_t cap;
};
void *
xmalloc(size_t s)
{
void *r = malloc(s);
if( r == NULL ){
perror("malloc");
exit(1);
}
return r;
}
void
allocate(void *p, size_t s)
{
*(int **)p = xmalloc(s * sizeof(int));
}
void
allocate2(struct intbuffer *p)
{
p->d = xmalloc(p->cap * sizeof *p->d);
}
int
main(void)
{
int *val2;
struct intbuffer v;
allocate(&val2, 10);
free(val2);
v.cap = 10; /* Horrible api!! */
allocate2(&v);
free(v.d);
return 0;
}
Note that setting the capacity in the struct prior to making the call to allocate is a violation of many principles of software design, but this whole thing is absurdly contrived due to the bizarre artificial limitations.
There are not enough *'s in each place, but you will have to figure out what that means.
void allocate(int** value){
*value = malloc(10 * sizeof(int));
}
int main(){
int* val2;
allocate(&val2);
free(val2);
return 0;
}

Double pointers in a linked list

I'm trying to store a string in a linked list, but for some reason, I keep getting segmentaion fault error.
I've tried everything, and I feel I'm missing something really stupid and easy, please any thoughts?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 60
typedef struct Node
{
char *getInput;
struct Node *next;
} Node;
typedef struct list
{
Node *head;
} list;
void readText(Node **a)
{
char c;
int i = 0;
while ((c = getchar()) != EOF)
(*a)->getInput[i++] = c;
}
void main()
{
Node *b;
b->getInput = (char *)calloc(SIZE, sizeof(char));
if (b == NULL)
{
printf("sadsa");
exit(1);
}
readText(&b);
printf("%s", b->getInput);
}
You mave to allocate a valid region and assign to b before dereferencing that.
Also checking if b is not NULL must be taken place before dereferencing.
You should use standard int main(void) in hosted environment instead of void main(), which is illegal in C89 and implementation-defined in C99 or later, unless you have some special reason to use non-standard signature.
getchar() returns int, so the return value should be assigned to an int variable. Otherwise, it will be difficult to distinguish between a valid character and EOF.
You should terminate strings by adding terminating null-character before using that for %s. (In this case it is not necessary because the buffer is initialized to zero via calloc(), but this will improve safety for another usage of the function)
void readText(Node **a)
{
int c; /* use proper type */
int i = 0;
while ((c = getchar()) != EOF)
(*a)->getInput[i++] = c;
(*a)->getInput[i] = '\0'; /* terminate the string */
}
int main(void) /* use standard signature */
{
Node *b = malloc(sizeof(*b)); /* allocate buffer */
if (b == NULL) /* check if allocation is successful before dereferencing */
{
printf("sadsa");
exit(1);
}
b->getInput = (char *)calloc(SIZE, sizeof(char));
readText(&b);
printf("%s", b->getInput);
}

Simply creating a data structure, how can it segfault?

i have a simple program on data structure but it segfaults and it frustrates me so much because i have absolutely no idea why. can anybody point out anything about this code (even not relevent)? thanks
#include <unistd.h>
#include <stdlib.h>
typedef struct prof
{
struct prof *next;
char c;
int x;
int y;
} profile;
profile *create_profile(char c, int i, int j)
{
profile *new_elem;
new_elem = (profile*)malloc(sizeof(profile));
if (new_elem == NULL)
return (NULL);
new_elem->next = NULL;
new_elem->c = c;
new_elem->x = i;
new_elem->y = j;
return (new_elem);
}
int main()
{
profile **king = NULL;
*king = create_profile('K', 1, 1);
return 0;
}
Your king is a pointer to a pointer to struct.
You need some place to store the pointer to struct in, but that is what you do not allocate.
You can introduce a pointer in order fix this.
int main()
{
/* introduce and NULL-init a pointer to struct */
profile* prince = NULL;
/* actually the init to NULL is not necessary,
because prince gets initialised later indirectly via king
(credits to alk), but it does not hurt and initialising everything
is a good habit. */
/* Introduce a pointer to pointer to struct,
initialised with the address of above pointer to struct,
the address of the above variable "prince" to be precise and clear.
The space for that automatic local variable is not dynamic,
it does not require a malloc. */
profile **king = &prince;
/* what the king is pointing to, i.e. the prince,
gets assigned what the function returns,
which is a cleanly allocated pointer to a new struct. */
*king = create_profile('K', 1, 1);
/* if king were still NULL, above statement would try to write
(the cleanly allocated pointer) into memory by dereferencing NULL ...
segfault!
(Well not necessarily, as alk points out, credits.
But dereferencing NULL is undefibed behaviour,
an almost guaranteed way to trouble in the long run
and in case a seggault is observed, a likely explanation.
*/
return 0;
}
This
profile **king = NULL;
*king = ...
dereferences NULL, which by itself already invokes undefined behaviour. On top of this the code then tries to write there. Not good, as NULL does not point to valid memory.
You have to allocate memory first to profile **king and then allocate memory to *king.
#include <unistd.h>
#include <stdlib.h>
typedef struct prof
{
struct prof *next;
char c;
int x;
int y;
} profile;
profile *create_profile(char c, int i, int j)
{
profile *new_elem;
new_elem = (profile*)malloc(sizeof(profile));
if (new_elem == NULL)
return (NULL);
new_elem->next = NULL;
new_elem->c = c;
new_elem->x = i;
new_elem->y = j;
return (new_elem);
}
int main()
{
profile **king = (profile**) malloc(sizeof(profile*)); // <-- see here
*king = create_profile('K', 1, 1);
return 0;
}
The code segfaults at
*king = create_profile('K', 1, 1);
Because you've defined king to
profile **king = NULL;
Meaning that king is now a pointer to a pointer. But king doesn't actually point anywhere, you say that it points to NULL. Dereferencing a pointer pointing to NULL will cause a segfault.
If you instead define king as
profile * king = NULL;
And assign it like
king = create_profile('K', 1, 1);
The code should no longer segfault.
You are confused in using double pointer. Try using like this
#include <unistd.h>
#include <stdlib.h>
typedef struct prof
{
struct prof *next;
char c;
int x;
int y;
} profile;
profile *create_profile(profile *head,char c, int i, int j)
{
profile *new_elem;
new_elem = (profile*)malloc(sizeof(profile));
if (new_elem == NULL)
return (NULL);
new_elem->next = head;
new_elem->c = c;
new_elem->x = i;
new_elem->y = j;
return (new_elem);
}
int main()
{
profile *king = NULL;
king = create_profile(king,'K', 1, 1);
return 0;
}

Function allocates always to the same address, and the variable doesn't change

The function f allocates its result always to the same address, that makes the main() function always print out the same result, how do I make the function allocate the variable an another address and free them.
int *f(int a) {
int b = 2 * a;
return &b;
}
int main(void) {
int *p4, *p8;
p4 = f(4);
p8 = f(8);
printf("p4: %i / p8: %i\n", *p4, *p8);
}
The function f does not allocate anything, it returns the address of a local variable with automatic storage. Accessing data via this pointer invokes undefined behavior as soon as b goes out of scope, when f returns. The compiler should be able to detect such a silly bug.
To allocate memory, you should use malloc:
#include <stdio.h>
#include <stdlib.h>
int *f(int a) {
int *p = malloc(sizeof(*p));
if (p != NULL)
*p = 2 * a;
return p;
}
int main(void) {
int *p4 = f(4);
int *p8 = f(8);
if (p4 != NULL && p8 != NULL) {
printf("p4: %i / p8: %i\n", *p4, *p8);
}
free(p4);
free(p8);
return 0;
}
You have to declare b as static ore better yet,declare b as parameter in f function. You could do something like this
static bool f(int a,int *b)
{
if(NULL == b)
{
return false;
}
*b = a * 2;
return true;
}
It is better to write functions that return nothing(void) or a boolean to let you know if everything went fine and use pointers to modify data and reduce the use of the stack. Most safety-critical standards adopt this rule.

Not understanding seg faults when I'm using pointers with structs

I keep getting seg faults and I can't for the life of me figure out why! I tried posting just the simplest example I could write up in code (what you see) to try and figure out the problem but I am stuck. Anything will help!!!!
int main()
{
int i1, i2;
struct intPtrs
{
int *p1;
int *p2;
};
struct intPtrs *myIntPtr;
i1 = 100;
i2 = 200;
myIntPtr->p1 = &i1;
myIntPtr->p1 = &i2;
printf("\ni1 = %i, i2 = %i\n",myIntPtr->p1,myIntPtr->p2);
return 0;
}
You haven't allocated memory for your struct. You need malloc (don't forget to free).
So, your code should look like this (there are others problems, check my code):
#include <stdio.h> // printf()
#include <stdlib.h> // malloc()
// declare the struct outside main()
struct intPtrs {
int *p1;
int *p2;
};
// typedef the struct, just for less typing
// afterwards. Notice that I use the extension
// _t, in order to let the reader know that
// this is a typedef
typedef struct intPtrs intPtrs_t;
int main() {
int i1, i2;
// declare a pointer for my struct
// and allocate memory for it
intPtrs_t *myIntPtr = malloc(sizeof(intPtrs_t));
// check if allocation is OK
if (!myIntPtr) {
printf("Error allocating memory\n");
return -1;
}
i1 = 100;
i2 = 200;
myIntPtr->p1 = &i1;
myIntPtr->p2 = &i2; // here you had p1
// you want to print the numbers, thus you need what the p1 and p2
// pointers point to, thus the asterisk before the opening parenthesis
printf("\ni1 = %d, i2 = %d\n", *(myIntPtr->p1), *(myIntPtr->p2));
// DON'T FORGET TO FREE THE DYNAMICALLY
// ALLOCATED MEMORY
free(myIntPtr);
return 0;
}
When I use structs, I also use a typedef, as you can see in my example here.

Resources