Seg fault while implementing malloc, realloc, free in C - c

I am implementing a simple version of malloc, realloc, and free for an assignment and having trouble debugging. My code seems to be working for malloc, but the realloc tests are resulting in a seg fault. Specifically, the pointer passed to free() seems to be the problem.
There is a "free list" to manage the list of previously allocated blocks of memory. Each node in this list maintains the next and previous blocks, and an int free which is set to 1 when the memory is available, 0 otherwise.
void *mm_malloc(size_t size) {
if (size <= 0) return NULL;
struct list_node *node;
if (!list_head) {
node = request_block(size);
list_head = node;
list_tail = node;
} else {
node = get_free_block(size);
if (!node) { //no available existing block
node = request_block(size);
if (!node) { //request failed
return NULL;
}
} else { //available existing block
//TODO: split block
node->free = 0;
}
}
return memset(node+1, 0, node->size);
}
void *mm_realloc(void *ptr, size_t size) {
if (size <= 0) return NULL;
if (!ptr) return mm_malloc(size);
struct list_node *node = (struct list_node*)ptr - 1;
if (node->size >= size) {
// TODO: free extra space
return ptr;
}
void *new_block = mm_malloc(size);
if (!new_block) return NULL;
memcpy(new_block, ptr, node->size);
free(ptr); //Error happens with this call.
return new_block;
}
void mm_free(void *ptr) {
if (!ptr) return;
struct list_node *node = (struct list_node*)ptr - 1;
node->free = 1;
}
EDIT: left out some important helper functions
struct list_node *get_free_block(size_t size) {
struct list_node *curr = list_head;
while (curr && !(curr->free && curr->size >= size)) {
curr = curr->next;
} return curr;
}
struct list_node *request_block(size_t size) {
struct list_node *node = sbrk(0);
void *request = sbrk(size + NODE_SIZE);
if (request == (void*) -1) { // attempted sbrk failed
return NULL;
}
if (list_tail) {
node->prev = list_tail;
list_tail->next = node;
list_tail = node;
}
node->next = NULL;
node->free = 0;
node->size = size;
return node;
}

Related

Why is "free" saying this that my pointer is invalid?

while(n >= 0);
node * point = malloc(sizeof(node));
point = create(number, n);
//show(point);
//free memory
while(point != NULL)
{
node *tmp = point->next;
free(point);
point = tmp;
}
}
node * create(int data[], int len)
{
node * list_head;
node * list;
for (int i = 0; i < len; i++)
{
if(i == 0)
{
list_head = malloc(sizeof(node));
list = malloc(sizeof(node));
list_head->value = data[0];
list_head->next = list;
}
else
{
list->value = data[i];
list->next = malloc(sizeof(node));
list->next = NULL;
}
}
return list_head;
}
This code is returning an error which is:- free(): invalid pointer
Aborted | Why is my code not freeing the memory that I allocated. Is it because I have allocated that in some different function?
The code you posted should be changed to:
while(n >= 0) {
node * point = create(number, n);
and:
list->next = NULL;
should be changed to
list = list->next;

Inserting integers into an array accessed via a pointer in C

I have a program that utilizes linked lists (as structs) to store integer elements (essentially on a stack). The problem is, when I insert integers into an array accessed via a pointer and try to print it, the numbers are not the integers that were entered (looks like a pointer, although not sure, when I try to dereference it, I get errors in compiling). New to C and this is for a class assignment, so looking more for explanations specifically on pointers and guidance as to what I may be doing wrong. I am attaching the code I've done.
For reference, the default size per node is 5 integers.
What running my code looks like:
What it should look like:
My guess is that the problem relies within the push/pop/top methods, although I did have some luck with using pointers in the make_node method, although then I got segmentation errors in the rest of the methods.
Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "int_stack.h"
/* Structure definitions from header file - all methods defined there as well.
struct is_node {
int *contents; Pointer to memory for storing up to node_capacity ints
(this has a fixed size and is determined at stack creation)
int next_index; Index of the next open position in the array of contents; starts at 0
struct is_node *next; Pointer to subsequent node in list (or NULL)
};
struct int_stack {
int size; Number of elements currently in stack
int node_capacity; Max elements per node
struct is_node *head; First node with stack contents; the contents
may be empty , but head should never be NULL
};
*/
struct is_node *make_node(int node_capacity);
/*
* Creates a stack, assigning appropriate variables.
*/
struct int_stack *make_stack(int node_capacity) {
struct int_stack *stack = NULL;
stack = malloc(sizeof(struct int_stack));
if (stack == NULL) {
fprintf(stderr, "Memory error!\n");
exit(-1);
}
stack->size = 0;
stack->node_capacity = node_capacity;
stack->head = make_node(node_capacity);
return stack;
}
/*
* Cleans up all memory used by the given stack.
*/
void free_stack(struct int_stack *stk) {
struct is_node *curnode = stk->head;
while (curnode != NULL) {
struct is_node *nextnode = curnode->next;
free(curnode);
curnode = nextnode;
}
free(stk);
}
/*
* Resets the stack, but allows it to still be used.
*/
void reset_stack(struct int_stack *stk) {
if (stk != NULL) {
struct is_node *curnode = stk->head;
while (curnode != NULL) {
struct is_node *nextnode = curnode->next;
free(curnode);
curnode = nextnode;
}
stk->size = 0;
stk->head = make_node(stk->node_capacity);
} else {
printf("Error: Stack is NULL. Cannot reset it.");
}
}
/*
* Prints the stack. Contents delimited with [] if node is at capacity
* or (] if not. The values of each node are seperated by commas.
*/
void print_stack(struct int_stack *stk) {
int i;
struct is_node *curnode = stk->head;
/* Count number of nodes */
int node_count = 1;
while (curnode->next != NULL) {
++node_count;
curnode = curnode->next;
}
/* Walk to end of stack and insert */
while (node_count > 0) {
curnode = stk->head;
for (i = 1; i < node_count; ++i) {
curnode = curnode->next;
}
if (curnode->next_index >= stk->node_capacity) {
printf("[");
} else {
printf("(");
}
for (i = curnode->next_index - 1; i >= 0; --i) {
if (i == 0) {
printf("%d]", curnode->contents[i]);
} else {
printf("%d,", curnode->contents[i]);
}
}
--node_count;
}
printf("\n");
}
/*
* Lets the user know if the stack is empty
*/
int is_empty(struct int_stack *stk) {
if(stk->size == 0) {
return 1;
}
return 0;
}
/*
* Pushes an int onto the stack
*/
void push(struct int_stack *stk, int v) {
/* Walk to end of stack and insert */
struct is_node *curnode = stk->head;
while (curnode->next != NULL) {
curnode = curnode->next;
}
if(curnode->next_index >= stk->node_capacity) {
struct is_node *new_node = make_node(stk->node_capacity);
new_node->contents[new_node->next_index] = v;
new_node->next_index += 1;
curnode->next = new_node;
} else {
curnode->contents[curnode->next_index] = v;
curnode->next_index = curnode->next_index + 1;
}
stk->size += 1;
}
/*
* Pulls the first int on the stack off the stack
*/
int pop(struct int_stack *stk) {
if (!is_empty(stk)) {
int top;
struct is_node *prevnode = stk->head;
struct is_node *curnode = stk->head;
struct is_node *nextnode = stk->head->next;
while (nextnode != NULL) {
if (nextnode->next != NULL) {
prevnode = curnode;
}
curnode = nextnode;
nextnode = curnode->next;
}
top = curnode->contents[curnode->next_index - 1];
curnode->next_index = curnode->next_index - 1;
if (curnode->next_index == 0) {
free(curnode);
curnode = NULL;
prevnode->next = NULL;
}
stk->size -= 1;
return top;
}
return -1;
}
/*
* Returns the top value from the stack.
*/
int top(struct int_stack *stk) {
struct is_node *curnode = stk->head;
while (curnode->next != NULL) {
curnode = curnode->next;
}
return curnode->contents[curnode->next_index - 1];
}
/*
* Helper method for creating nodes in the stack.
*/
struct is_node *make_node(int node_capacity) {
struct is_node *node = malloc(sizeof(struct is_node));
if (node == NULL) {
fprintf(stderr, "Memory error!\n");
exit(-1);
}
node->next = NULL;
node->next_index = 0;
int node_contents[node_capacity];
node->contents = node_contents;
return node;
}
make_node() sets node->contents to a local variable that will go out of scope as soon as the function ends. If you use contents outside the function you'll have undefined behavior.

Simple malloc function in c

#define SIZE 7000
static char buf[SIZE];
static char *bufptr = buf;
struct node
{
int reg_num;
int val;
char var_name[30];
char var_str[100];
struct node *memroy;
struct node *next;
};
struct node* add(struct node *head, int i)
{
struct node *temp;
if (head == NULL)
{
temp = (struct node *)malloc(sizeof(struct node));
temp->next = NULL;
temp->reg_num = i;
head = temp;
}
else
{
head->next = add(head->next, i);
}
return head;
}
void* malloc(int n)
{
if (buf + SIZE - bufptr >= n)
{
bufptr += n;
return bufptr - n;
}
else
{
return NULL;
}
}
When I run my programm it crashes during the assignment temp->next = NULL.
I think the problem is in my malloc function. I tested it with malloc in libraries and it worked correctly, but I not allowed to use libraries and must write a new malloc function.
You never check the return of your malloc yet you know it can return NULL;.
Check if temp is NULL before doing temp->next = NULL;
My problem don't has relation with kind of pointer and returned value from malloc().I have problem with size of buf[] and by increment of size my problem solved.Tnx from every one.

C - double free

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct strqueue {
struct lnode *front;
struct lnode *back;
int length;
};
struct lnode {
char *item;
struct lnode *next;
};
StrQueue create_StrQueue(void) {
struct strqueue *sq = malloc(sizeof(struct strqueue));
sq->length = 0;
sq->front = NULL;
sq->back = NULL;
return sq;
}
void destroy_nodes(struct lnode *l) {
while (l!=NULL) {
struct lnode *c = l;
l=l->next;
free(c);
}
}
void destroy_StrQueue(StrQueue sq) {
destroy_nodes(sq->front);
free(sq);
}
void sq_add_back(StrQueue sq, const char *str) {
struct lnode *n = malloc(sizeof(struct lnode));
n->item = malloc(sizeof(char)*(strlen(str)+1));
strcpy(n->item, str);
n->next = NULL;
if (sq->length == 0) {
sq->front = n;
sq->back = n;
} else {
sq->back->next = n;
sq->back = n;
}
sq->length++;
}
char *sq_remove_front(StrQueue sq) {
if (sq->front == NULL) {
return NULL;
} else {
struct lnode *f = sq->front;
char *temp = sq->front->item;
sq->front = sq->front->next;
sq->length--;
//Delete the line below will not cause an error of not free all memory
free(f->item);
free(f);
return temp;
}
}
int sq_length(StrQueue sq) {
return sq->length;
}
Here I wanna make the strqueue like a linked list but when I use it, it always says that I am attempting to double free something. Which part of my code is wrong? Is there a memory leak or something wrong about the memory allocation?
In
struct lnode *f = sq->front;
char *temp = sq->front->item;
sq->front = sq->front->next;
sq->length--;
//Delete the line below will not cause an error of not free all memory
free(f->item);
free(f);
return temp;
It returns pointer temp to freed memory in free(f->item), reading the string through that pointer is undefined behaviour. And if you free it that is going to be the double free. Basically, the returned pointer is useless.
The fix would be to avoid doing free(f->item) in that function. The caller would need to free the pointer to the string after use.
Singly-linked list is best represented by:
struct lnode *head, **tail;
Initialized as:
head = NULL;
tail = &head;
In this case there is no need for special handling of an empty list on appending. Appending always is:
*tail = n;
tail = &n->next;
Removing from the front is:
struct lnode *n = head;
if(head) {
head = head->next;
if(!head)
tail = &head;
}
return n;
You could try this in char *sq_remove_front(StrQueue sq) :
if (f->item != NULL) {
free(f->item);
f->item = NULL;
}
if (f != NULL) {
free(f);
sq->front = NULL;
}
It would avoid performing free() twice on the pointers.

Segmentation Fault (core dumped) in C in Delete() function

i am writing a Dictionary using linked list in C, and all my functions work except my delete function, which is shown below along with all other necessary code. Every time i try to run my program as soon as it reaches a line in which it must delete a node, it gives me the error: Segmentation Fault (core dumped) which means it has something to do with the memory allocation or a null pointer i think. I know that the rest of my code works. All and any help is appreciated! :)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include"Dictionary.h"
// NodeObj
typedef struct NodeObj{
char* key;
char* value;
struct NodeObj* next;
} NodeObj;
// Node
typedef NodeObj* Node;
// newNode()
// constructor of the Node type
Node newNode(char* key, char* value)
{
Node N = malloc(sizeof(NodeObj));
assert(N!=NULL);
// if(key!=NULL && value!=NULL){
N->key = key;
N->value = value;
N->next = NULL;
// }
return(N);
}
// DictionaryObj
typedef struct DictionaryObj{
Node head;
int numItems;
} DictionaryObj;
// newDictionary()
// constructor for the Dictionary type
Dictionary newDictionary(void){
Dictionary D = malloc(sizeof(DictionaryObj));
assert(D!=NULL);
D->head = NULL;
D->numItems = 0;
return D;
}
Node findKey(Dictionary D, char*key){
Node N;
N = D->head;
while(N != NULL){
if(strcmp(N->key,key)==0){
return N;
}
N = N->next;
}
return NULL;
}
char* lookup(Dictionary D, char* k){
if(findKey(D, k)==NULL){
return NULL;
}else{
Node N;
N = findKey(D, k);
return N->value;
}
}
void delete(Dictionary D, char* k)
{
if(lookup(D,k) == NULL){
fprintf(stderr,
"KeyNotFoundException: Cannot delete non-existent key\n");
exit(EXIT_FAILURE);
}
int check = strcmp(D->head->key, k);
if(check == 1){
D->head = D->head->next;
return;
}
Node cur;
Node prev;
cur = D->head;
prev = NULL;
while( cur != NULL){
int ret1;
ret1 = strcmp(cur->key, k);
while( ret1 == 0){
prev = cur;
cur = cur->next;
}
}
prev->next = cur->next;
D->numItems--;
}
The NodeObject should store copy of the string and care for deleting it:
typedef struct Node Node;
struct Node {
Node *next;
char *key, *value;
};
Node* newNode(char* key, char* value) {
assert(key && value);
Node* node = (Node*)malloc(sizeof(Node));
assert(node);
node->next = NULL;
node->key = strdup(key);
node->value = strdup(value);
}
void delNode(Node* node) {
free(node->key);
free(node->value);
}
Consider using the original code (without that strdup) in this scenairo:
Node* prepare() {
char key_buf[20]; strcpy(key_buf, "mykey");
char val_buf[20]; strcpy(val_buf, "myval");
return newNode(key_buf, val_buf);
}
void examine(Node* node) {
printf("Node key=%s value=%s\n", node->key, node->value);
}
int main() {
examine(prepare());
}
the above code would crash because Node would have pointers to stack (in your case without that strdup), but key_buf+val_buf were only valid inside prepare() (garbage outside and therefore inside examine() - node->key points to random data).

Resources