seg fault after trying to access ladder part of sbrk free space - c

Ok, so I have a struct that looks like
typedef struct meta {
size_t size;
struct meta* next;
struct meta* prev;
} meta_t;
I also statically allocate the beginning list pointer and the end list pointer as:
static meta_t* freelist_b = NULL;
static meta_t* freelist_e = NULL;
I then free a block of 4 MB of space and set the beginning list pointer to it
size_t max_bytes = ALIGN(1024*1024*4);
freelist_b = (meta_t*) sbrk(max_bytes);
Then I try to do the same for the end of list pointer
freelist_e = memcpy(freelist_b+max_bytes-sizeof(meta_t),freelist_b,sizeof(meta_t));
But this line gives a segmentation fault. Can anyone tell me what I'm doing wrong or how to further debug this? Thanks.

When you do freelist_b+max_bytes-sizeof(meta_t), you are using operator+ on a pointer to a meta_t structure. This adds a lot more than what you probably expect.
Change:
freelist_b
To:
(char*)freelist_b
Or change:
max_bytes-sizeof(meta_t)
To:
max_bytes/sizeof(meta_t)-1

Related

Why do I get a segfault when trying to access members of struct?

I am getting a segmentation fault whenever I try to print the value stored within a struct. Using Valgrind, I was able to narrow it down a bit to one block of code, but I am unsure what I am doing wrong. Am I initializing my struct incorrectly?
Whenever I run valgrind, it tells me that there is an invalid write of size 8 where I say newList->data = d.
typedef struct List {
struct List *np[Ends]; // next/prev neighbors
Data data;
} *List;
typedef void *Data;
static void put(Data d) {
List newList = malloc(sizeof(List));
newList->data = d;
}
This is an example of why it's bad practice to typedef a pointer.
Because List is defined as an alias for struct List *, sizeof(List) gives you the size of a pointer, not the size of the struct. As a result, you're not allocating enough memory.
You instead want either malloc(sizeof(struct List)) or (preferably) malloc(sizeof *newlist)

C destroying what I have behind when adding to list

I'm writing a program that needs to execute a list of commands so i'm using this struct to save them
typedef struct clist {
struct clist *prox;
char comando[];
} *CommandList;
And this function to add to make the last node point to a new node
void addToList (CommandList list, CommandList x){
CommandList temp = list;
while (temp->prox != NULL)
temp = temp->prox;
temp->prox = x;
}
However when I call the adding function I seem to lose everything that I had behind and I seriously can't understand why this is happening, this is the piece of code where that
aux = (CommandList) malloc(sizeof(struct clist));
strcpy(aux->comando,cropString(string));
aux->prox = NULL;
addToList(list,aux);
free(aux);
print_list(list);
When I call the print_list function the only node that is printed is the one I just added, and later on in the code I get a segfault, can someone help please?
This happens because you are misusing flexible struct member: when you define an array member like this
char comando[];
it means that you will allocate space for it manually; C compiler cannot do it for you.
You fix it by allocating additional space in malloc for the string that you save in comando, like this:
const char* cropped = cropString(string);
aux = malloc(sizeof(struct clist)+strlen(cropped)+1);
strcpy(aux->comando, cropped);
You are allocating "aux", adding it to your list, and then freeing aux. So you now have a list that points to a deallocated chunk of memory. When you allocate memory, you have to not deallocate it until you are done using it.

Singly Linked List in C incorrect output

So I'm doing some linked list revison and Im trying to just load a list with some numbers and then print it out. Below is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct stack {
int data;
struct stack *next;
}*stack;
stack create_s(void){
stack s = (void*)malloc(sizeof(stack));
s->next = NULL;
return s;
}
void push_s(stack s, int data) {
while (s->next != NULL) {
s = s->next;
}
s->next = (void*)malloc(sizeof(stack));
s=s->next;
s->data = data;
s->next = NULL;
}
void print_s(stack s) {
if (s==NULL) {
return;
}
else {
while (s->next != NULL) {
printf("%d\n",s->data);
s=s->next;
}
}
}
int main (void) {
stack s = create_s();
push_s(s,2);
push_s(s,4);
push_s(s,6);
push_s(s,8);
print_s(s);
return 0;
}
My output is however:
-1853045587
2
4
6
when it should be
2
4
6
8
Is it printing the address of my struct at the beginning? Also, why is it not printing my last element?
Thanks
The code contains several errors, but the first thing that catches the eye is that your memory allocation is already obviously broken
stack s = (void*)malloc(sizeof(stack));
You defined stack as a pointer type. This means that sizeof(stack) evaluates to pointer size and the above malloc allocates enough space to store a single pointer, not enough for the entire struct stack object. The same memory allocation error is present in push_s as well.
Here's some advice
Don't hide pointer types behind typedef names. Define your stack as
typedef struct stack{
int data;
struct stack *next;
} stack;
and use stack * wherever you need a pointer. I.e. make that * visible instead of hiding it "inside" a typedef name. This will make your code easier to read.
Don't cast the result of malloc. Anyway, what is the point of casting it to void * when it is void * already???
Don't use sizeof with types unless you really really have to. Prefer to use sizeof with expressions. Learn to use the following malloc idiom
T *p = malloc(sizeof *p);
or, in your case
struct stack *s = malloc(sizeof *s);
This will allocate a memory block of appropriate size.
Also, as #WhozCraig noted in the comments, the very first node in your list is apparently supposed to serve as a "sentinel" head node (with undefined data value). In your code you never initialize the data value in that head node. Yet in your print_s function you attempt to print data value from the head node. No wonder you get garbage (-1853045587) as the first line in your output. Don't print the very first node. Skip it, if it really is supposed to serve as a sentinel.
Also, the cycle termination condition in print_s looks strange
while (s->next != NULL)
Why are you checking s->next for NULL instead of checking s itself? This condition will terminate the cycle prematurely, without attempting to print the very last node in the list. This is the reason why you don't see the last element (8) in your output.
The actual cause of the given output can be fixed by changing:
s=s->next;
s->data = data;
to
s->data = data;
s=s->next;

Mysterious segmentation fault while creating a Linked List (Add function)

Im trying to create a Linked List in C but the program crashed due to some mysterious fault.
First I tried this:
typedef struct product_data product_data;
struct product_data {
int product_code;
int product_size;
product_data *next;
};
product_data *products_head = NULL;
product_data *products_tail = NULL;
int main() {
int newcode = 5;
int newsize = 5;
products_head->product_code = newcode;
products_head->product_size = newsize;
products_head->next = NULL;
return 0;
}
Unfortunately the program crashes without any error message.
Then I changed some parts:
typedef struct product_data product_data;
struct product_data {
int product_code;
int product_size;
product_data *next;
};
product_data *products_head = NULL;
product_data *products_tail = NULL;
int main() {
product_data *newproduct;
int newcode = 5;
int newsize = 5;
newproduct->product_code = newcode;
newproduct->product_size = newsize;
newproduct->next = NULL;
products_head = newproduct;
return 0;
}
No crash this time, it seems to work. I have no idea why though.
Any ideas?
Thanks in advance!
It doesn't really work. You're still dereferencing invalid pointers:
product_data *newproduct;
int newcode = 5;
int newsize = 5;
newproduct->product_code = newcode;
newproduct->product_size = newsize;
newproduct->next = NULL;
But while in the first version you were dereferencing pointers explicitly set to NULL, it crashed with a segmentation fault like it should. Here you are dereferencing a pointer that contains whatever data lay on the stack, and unfortunately it doesn't crash. It's undefined behaviour, so it need not necessarily crash.
You have to let your pointers point to valid memory,
newproduct = malloc(sizeof product_data);
You need to allocate memory for products_head. Right now you're just setting it to NULL. Either don't make it a pointer, or use malloc.
In your first sample, you are writing to a NULL pointer. You need to allocate space for products_head before you dereference it. Something like
products_head = malloc(sizeof(product_data));
I don't know why your second example worked. It shouldn't. newproduct is an uninitialized variable, it could point anywhere. Maybe you just got lucky and it pointed to an unused chunk of valid memory.
This will work until it does not. You still do not have any allocated memory for your struct. But due to some luck, newproduct points to some memory location that is valid. The issue you are facing, product_head was manually set to null (even though this is not needed, since all global variables are always initialized). Stack variables however are not initialized, and you were lucky (or unlucky that it would have caused you to miss a blatant programming mistake) that it happened to point to somewhere valid in your address space.
You can print the content of newproduct to see where it is pointing using printf("%p", newproduct); Unfortunately, inserting this line may change the behavior of the program.
The "->" is meant to access an element in a structure that is dynamically allocated and "." is used to access an element in a structure that is statically allocated.
Here is an example:
typedef struct product_data product_data;
struct product_data {
int product_code;
int product_size;
product_data *next;
};
product_data *products_head = NULL;
product_data *products_tail = NULL;
int main() {
/* Allocate memory */
product_data *newproduct = malloc(sizeof(product_data));
int newcode = 5;
int newsize = 5;
products_head = newproduct;
newproduct->product_size = newsize;
newproduct->next = NULL;
/* free memory */
free(product_data);
return 0;
}
But remember that for all the new nodes that you make in the linked list you will have to allocate memory and free that memory. A good program to use to check that all the memory you allocated was free'd is valgrind. And if you run into logic errors trying to make the linked list draw it out by hand first like this:
[head] [tail]
| |
V V
[ a ] -> [ b ] -> null
Just remember that head and tail are both pointers (so they do not need to be allocated memory, they just need to be POINTING at the node that you want.
If you still run into problems because your logic gets very complicated I sugget you try and learn GDB (it is a command line debugger) it will help you step through your code so you can see what is happening step by step. That is how I first learnt to create data structure.
Good Luck!

Need some help understanding pointers and memory in C

I'm writing a bit of code for a class, but since I have no experience in C I'm a bit unsure of what the code I've written actually does. Particularly what the memory looks like. Here's the relevant bits:
typedef struct listnode *Node;
typedef struct listnode {
void *data;
Node next;
Node previous;
} Listnode;
typedef struct listhead *LIST;
typedef struct listhead {
int size;
Node first;
Node last;
Node current;
} Listhead;
#define HALLOCSIZE 50
static LIST hallocbuf[HALLOCSIZE];
static LIST *hallocp = hallocbuf;
LIST *CreateList()
{
if(hallocbuf + HALLOCSIZE - hallocp >= 1)
{
LIST temp;
temp->size = 0;
temp->first = NULL;
temp->last = NULL;
temp->current = NULL;
*hallocp = temp;
return hallocp;
}else
return NULL;
}
So my question is, in the CreateList function, how is the program allocating memory for temp? And does the code *hallocp = temp copy the temp LIST into the hallocbuf array? I am trying to have all my LIST structs sit in the allocated memory for hallocbuf. Is this what I'm doing? I'm a bit uncertain of how the typedef, structs and pointers play together.
Thanks!
So my question is, in the CreateList function, how is the program allocating memory for temp?
It isn't, which is a problem. It should do something like this:
temp = malloc(sizeof(Listhead));
And does the code *hallocp = temp copy the temp LIST into the hallocbuf array?
It copies the pointer that was saved in temp into the first element of hallocbuf (assuming that hallocp hasn't been changed anywhere and still has the value that it has been initialized to, pointing to hallocbuf[0]).
Generally it's not usually a good idea to hide the fact that LIST and Node are pointers behind typedefs. It's much clearer where memory needs to be allocated of freed if it's obvious which variables are pointer, and having an explicit * in the variable declaration makes that clear.
temp is allocated in the space used for objects with "automatic storage duration" - this is usually on a runtime stack, but you don't really need to know the details. The space is deallocated when the block in which it was allocated is exited (in your case, when you hit the return).
The line *hallocp = temp; does indeed copy the value of temp into the memory that hallocp is pointing at, which is hallocbuf[0].
The problem is that temp is just a pointer itself - and it's not pointing at anything. This is called a "dangling pointer". This means that when you try to access what it's pointing at, you have an error. That happens in these lines:
temp->size = 0;
temp->first = NULL;
temp->last = NULL;
temp->current = NULL;
You can't have your structs sit in the memory allocated for hallocbuf, because it doesn't have room for structs - it's just an array of pointers, not an array of structs.
If LIST were
typedef struct listhead LIST;
and you accessed temp
temp.size = 0;
...
then
*hallocp++ = temp;
would use hallocp as a pointer into the hallocbuf buffer and place the newly initialized element there. Not the best way to do it, though. You could replace temp with
hallocp->size = 0;
...
++hallocp;

Resources