Getting a malloc error when not using printf() - c

#include <stdio.h>
#include <stdlib.h>
typedef struct lis
{
int num;
struct lis * next;
} list;
void fun(list ** h, int nu) {
*h = malloc(sizeof(list)*nu);
list *p = *h;
int i=1;
list * nextx;
while(i<=nu) {
nextx = p + 1;
p->num = i;
p->next = nextx;
//printf("%d\n", nextx);
p += 1;
i++;
}
p->next = NULL;
}
int main(int argc, char const *argv[])
{
list * first = NULL;
fun(&first,10);
free(first);
return 0;
}
I'm learning lists in c
whenever this code is run it gives an malloc error
if i comment out printf("%d\n", nextx); which shows next node it works fine.
what is happening?

In the last run of the loop, your code do:
nextx = p+1; // points one past the last array' element
p->num = nu-1; // ok
p->next = p+1; // probably not what you wanted, but not a fault per se
p += 1; // This is the cause of your problem
i++; // out of the loop...
p->next = NULL; // dereference out of array pointer!
Quit the loop one step before and then set the last element correctly:
while (i<nu) {
...
}
p->next = NULL;
p->num = nu-1;

Related

c deleting element in dynamic struct

i'm trying to delete a single element in the struct and override this position with the last one.
Here is my code of a function:
int deleteElement(struct record **rec, int *length, int elementToDelete){
struct record *temp = NULL;
allocateTempMemory(&temp, ((*length) - 1));
for (int i = 0; i < ((*length) - 1); i++){
if (elementToDelete != i){
temp[i] = (*rec)[i];
temp[i].ID = (*rec)[i].ID;
temp[i].Salary = (*rec)[i].Salary;
strcpy(temp[i].Name, (*rec)[i].Name);
} else {temp[i] = (*rec)[(*length) - 1];
temp[i].ID = (*rec)[(*length) - 1].ID;
temp[i].Salary = (*rec)[(*length) - 1].Salary;
strcpy(temp[i].Name, (*rec)[(*length) - 1].Name);
};
}
free(*rec);
*rec = temp;
for (int i = 0; i < ((*length) - 1); i++){
(*rec)[i] = temp[i];
(*rec)[i].ID = temp[i].ID;
(*rec)[i].Salary = temp[i].Salary;
strcpy((*rec)[i].Name, temp[i].Name);
}
(*length)--;
free(temp);
return 1;
}
code of the struct
struct record{
char Name[100];
double Salary;
int ID;
};
code of the function allocateTempMemory:
int allocateTempMemory(struct record **temp, int length){
*temp = (struct record **)malloc(sizeof(struct record) * length);
if (temp == NULL){
return 0;
}
return 1;
}
However, it does not work properly. My guess are memory allocation issues (sometimes it runs through and sometimes it crashes immediately). Do you have any idea what the problem may be? thanks
You assign temp to *rect, than you free temp. basically you freed *rec. When you access *rec later it will cause crash.
*rec = temp;
....
free(temp); // cause *rec freed. Should not be freed.

creating and displaying a linked list in c: program not displaying correctly

currently working on a program to create a poker game. Right now I'm trying to get the deck of cards to print. It's not printing anything, and instead of exiting with code zero when I run it, it exits with code -104356 or something like that. I'm using two functions, one to make the cards, and the other to print them, and I'm not sure where the problem is.
my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct card_s {
char suit;
int face;
struct card_s* next;
} card;
card* createCard(int n);
void printCard(card* head);
int main(void) {
card* first = NULL;
first = createCard(52);
printCard(first);
free(first);
return(0);
}
card * createCard(int n) {
int i = 0;
card* head = NULL;
card* tmp = NULL;
card* p = NULL;
for (i = 0; i < n; i++) {
tmp = (card*)malloc(sizeof(card));
tmp->face = rand() % (10 + 1 - 1) + 1; //this is supposed to generate a random number between 1 and 10
tmp->suit = "CDHS"[rand() % 4]; //this is supposed to generate a random letter C, D, H, or S
tmp->next = NULL;
if (head == NULL) {
head = tmp;
}
else {
p = head;
while (p != NULL) {
p = p->next;
}
p->next = tmp;
}
}
return(head);
}
void printCard(card * head) {
card* p = head;
while (p->next != NULL) {
printf("%d%s\n", p->face, p->suit);
p = p->next;
}
return;
}
In this code snippet
else {
p = head;
while (p != NULL) {
p = p->next;
}
p->next = tmp;
}
after the while loop the pointer p is equal to NULL. So the next statement
p->next = tmp;
invokes undefined behavior.
You need at least to rewrite the loop like
while (p->next != NULL) {
p = p->next;
}
But in any case such an approach is inefficient. It is better to write
if (head == NULL) {
head = tmp;
p = head;
}
else {
p->next = tmp;
p = p->next;
}
Also within the function printCard the last element of the list is not outputted due to the condition in the while loop
while (p->next != NULL) {
Also you may not use the conversion specifier %s with an object of the type char as you are doing
printf("%d%s\n", p->face, p->suit);
The function can be written like
void printCard( const card *head )
{
for ( ; head != NULL; head = head->next )
{
printf("%d%cn", head->face, head->suit);
}
}
Others have already pointed out the potential issues with your implementation of the linked list, so I will chip in with a somewhat different point.
You might want to store your deck of cards in a linked list--I don't know your implementation, so whether that is a good idea or not, I cannot say, but it can certainly make sense--but this doesn't mean that you have to allocate each card separately or initialise them one by one. You can create a deck of cards as an array and still chain them up with pointers.
If you do that, you can allocate and free them as a whole, and you avoid the irritating special case when you wish to prepend/append to an empty list. You can have all your cards at once, and then chain them up.
Such an approach might also make it easier to shuffle the cards. With an array, you can easily create a random permutation, and then chain the cards up based on that. Permuting a linked list can be a little harder.
As I said, I don't know the application, so I have no idea if this good or bad advice, but I have put some example code below.
#include <stdio.h>
#include <stdlib.h>
#define DECK_SIZE 52
struct card
{
char suit;
char const *face;
struct card *next;
};
struct card *alloc_deck(void)
{
static char const *suite = "CDHS";
static char const *face[] = {
"A", "2", "3", "4", "5", "6",
"7", "8", "9", "10", "J", "Q", "K",
NULL};
struct card *deck = malloc(DECK_SIZE * sizeof *deck);
struct card *card = deck;
for (char const *s = suite; *s; s++)
{
for (char const **f = face; *f; f++)
{
*card = (struct card){
.suit = *s,
.face = *f,
.next = card + 1 // point to next card
};
card++;
}
}
// last card should point to zero
(card - 1)->next = NULL;
return deck;
}
void print_card_list(struct card *deck)
{
for (struct card *card = deck; card; card = card->next)
{
printf("%s%c\n", card->face, card->suit);
}
}
void print_deck_array(struct card *deck)
{
for (int i = 0; i < DECK_SIZE; i++)
{
printf("%s%c\n", deck[i].face, deck[i].suit);
}
}
struct card *shuffle(struct card *deck)
{
static int perm_init;
static int perm[DECK_SIZE];
if (!perm_init)
{
perm_init = 1;
for (int i = 0; i < DECK_SIZE; i++)
{
perm[i] = i;
}
}
// permute indices
for (int i = DECK_SIZE - 1; i >= 0; --i)
{
int j = rand() % (i + 1);
int temp = perm[i];
perm[i] = perm[j];
perm[j] = temp;
}
// chain up the cards
for (int i = 0; i < DECK_SIZE - 1; i++)
{
deck[perm[i]].next = &deck[perm[i + 1]];
}
deck[perm[DECK_SIZE - 1]].next = NULL; // terminate chain
return &deck[perm[0]]; // return first in chain
}
int main(void)
{
struct card *deck = alloc_deck();
printf("Allocated list:\n");
print_card_list(deck);
printf("\n");
printf("Allocated array:\n");
print_deck_array(deck);
printf("\n");
struct card *card = shuffle(deck);
printf("Shuffled deck:\n");
print_card_list(card);
printf("\n");
card = shuffle(deck);
printf("Second shuffled deck:\n");
print_card_list(card);
printf("\n");
free(deck); // free deck as a whole
return 0;
}

why the tail of this autoexpand list can't successfully display?

I want to use carriage return to end up input,but why the list lost its last element. I have check my code but can't figure out why the NUll was pointed by the penult instead of the last one. The first function is to automatically establish the list, and I use \n as the sign to end up input.
#include <stdio.h>
#include <stdlib.h>
typedef struct number {
int num;
struct number* pnext;
} number;
number* autoexpand()
{
char c;
int n = 0;
number *head = NULL, *p1, *p2;
p1 = p2 = (number*)malloc(sizeof(number));
scanf("%d", &p1->num);
while (c = getchar() != '\n') {
n++;
if (n == 1) {
head = p1;
}
else {
p2->pnext = p1;
}
p2 = p1;
p1 = (number*)malloc(sizeof(number));
scanf("%d", &p1->num);
}
p2->pnext = NULL;
return head;
}
void print(number* p)
{
for (; p != NULL; p = p->pnext) {
printf("%d ", p->num);
}
printf("\n");
}
int main()
{
number *p, *q;
p = autoexpand();
print(p);
for (; p != NULL;) {
q = p;
p = p->pnext;
free(q);
}
}
Output:
5 4 3 2 1
5 4 3 2
I have to admit that the use of getchar + scanf is a bit confusing to me.
I haven't tested the program but I can see the following bug in the code:
At the end of the function you are missing the last pointer p1, when you go out of the while loop you should save p1 and then add NULL as tail.
p2->pnext = p1;
p1->pnext = NULL;
return head;
I think it should do the trick.

segmentation fault in a linked list while loop?

I'm trying to setup a graph in C. I tried the graph with user input and it works perfectly. However, i am trying to implement a read from file. The last else statement is where the error is coming from because when i commented it out it compiles without any problems. I have included a comment over the block i think that has the problem. Please let me know if there is anything else needed for this question.
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
struct node* next;
};
//int counter and mainVertex would be used to determine if graph is connected.
// void graphConnection(){
//
//
//
//
//
//
// }
char* deblank(char* input)
{
int i,j;
char *output=input;
for (i = 0, j = 0; i<strlen(input); i++,j++)
{
if (input[i]!=' ')
output[j]=input[i];
else
j--;
}
output[j]=0;
return output;
}
struct node *G[1000];
int counter = 0;
char *mainVertex;
void readingEachLine(){
FILE * fp;
char * line = NULL;
size_t len = 0;
ssize_t read;
//Read file and exit if fail
fp = fopen("test.txt", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1) {
line = deblank(line);
int i = 0;
struct node* cursor = malloc(sizeof(struct node));
struct node* secondcursor = malloc(sizeof(struct node));
struct node* tempitem;
while(line[i] != '\n'){
//If its the first of the line look into the array and set struct cursor to the corresponding
//array position
if (i == 0){
mainVertex[counter] = line[0];
int convertor = line[i] - '0';
cursor = G[convertor];
counter++;
}
//if its not the first, then set a struct with that number as data
else{
tempitem = malloc(sizeof(struct node));
int convertor = line[i] - '0';
tempitem->data = convertor;
tempitem->next = NULL;
}
//if there is no element connected to the struct in array, connect the tempitem
if (cursor->next == NULL){
cursor->next = tempitem;
}
//If there are already connected elements, loop until the end of the linked list
//and append the tempitem
//ERROR: I GET SEGMENTATION FAULT FROM HERE. TRIED AFTER COMMENTING IT OUT
else{
secondcursor = cursor;
while(secondcursor->next != NULL){
secondcursor = secondcursor->next;
}
secondcursor->next = tempitem;
}
i++;
}
printf("\n");
}
}
int main(void){
for (int i = 1; i < 1000; i++)
{
G[i]= malloc(sizeof(struct node));
G[i]->data = i;
G[i]->next = NULL;
}
readingEachLine();
}
EDIT: This is how the text file looks like:
1 3 4
2 4
3 1 4
4 2 1 3
Your code has several misconceoptions:
Apparently, you can have a maximum of 1,000 nodes. You have an array G of 1,000 head pointers to linked lists. Don't allocate memory for all 1,000 nodes at the beginning. At the beginning, all lists are empty and an empty linked list is one that has no node and whose head is NULL.
In your example, cursor is used to iterate oer already existing pointers, so don't allocate memory for it. If you have code like this:
struct node *p = malloc(...);
// next use of p:
p = other_node;
you shouldn't allocate. You would overwrite p and lose the handle to the allocated memory. Not all pointers have to be initialised with malloc; allocate only if you create a node.
Your idea to strip all spaces from a line and then parse single digits will fail if you ever have more then 9 nodes. (But you cater for 1,000 node.) Don't try to parse the numbers yourself. There are library functions for that, for example strtol.
It is not clear what mainVertex is supposed to be. You use it only once, when you assign to it. You treat it like an array, but it is a global pointer, initialised to NULL. When you dereference it, you get undefined behaviour, which is where your segmentation fault probably comes from.
Here's a program that does what you want to do. (It always inserts nodes at the head for simplicity and it should have more allocation checks.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum {
maxNodes = 1000
};
struct node{
int data;
struct node* next;
};
struct node *G[maxNodes];
size_t nnode = 0;
int read_graph(const char *fn)
{
FILE * fp;
char * line = NULL;
size_t len = 0;
fp = fopen(fn, "r");
if (fp == NULL) return -1;
while (getline(&line, &len, fp) != -1) {
char *p;
char *end;
int id;
int n;
id = strtol(line, &end, 10);
if (end == line) continue;
if (id < 1 || id > maxNodes) break;
if (id > nnode) nnode = id;
id--;
p = end;
n = strtol(p, &end, 10);
while (p != end) {
struct node *nnew = malloc(sizeof(*nnew));
nnew->data = n - 1;
nnew->next = G[id];
G[id] = nnew;
p = end;
n = strtol(p, &end, 10);
}
}
fclose(fp);
free(line);
return 0;
}
int main(void)
{
if (read_graph("test.txt") < 0) {
fprintf(stderr, "Couldn't gread raph.\n");
exit(1);
}
for (int i = 0; i < nnode; i++) {
struct node *p = G[i];
if (p) {
printf("%d:", i + 1);
for (; p; p = p->next) {
printf(" %d", p->data + 1);
}
puts("");
}
}
for (int i = 0; i < nnode; i++) {
struct node *p = G[i];
while (p) {
struct node *old = p;
p = p->next;
free(old);
}
}
return 0;
}

Linked List program error? In C

Trying to study linked list and tried my program on gcc 4.1.2 on terminal and Xcode.
xcode Error: Thread 1: Exe_BAD_ACCESS(Code=1)
Terminal Error; Segmentation fault
and i have no clue what the xcode error is. for some reason it gives me that same error for some programs that work on other gcc?
Code :
#include <stdio.h>
#include <stdlib.h>
typedef struct node *link;
struct node {int item; link next;};
int main(int argc, const char * argv[]) {
int i;
link t = malloc(sizeof *t);
while ( t != NULL)
{
for ( i = 0; i < 10;i++)
{
t->item = i;
t = t->next;
}
}
int count = 0;
while ( t != NULL)
{
for ( i = 0; i < 10; i++)
{
if (count == 3)
{
printf("%d\n", t->item);
continue;
}
t = t->next;
count++;
}
}
}
You dereferenced t->next, which is allocated via malloc() and not assigned some value, and invoked undefined behavior. You have to allocate buffer for second node and later.
Also you should get the pointer t back before dealing with the list.
#include <stdio.h>
#include <stdlib.h>
typedef struct node *link;
struct node {int item; link next;};
int main(int argc, const char * argv[]) {
int i;
link t = malloc(sizeof *t);
link head = t; /* add this line to get the pointer back */
while ( t != NULL)
{
for ( i = 0; i < 10;i++)
{
t->item = i;
t->next = malloc(sizeof *t); /* add this line */
t = t->next;
}
}
int count = 0;
t = head; /* add this line to get the pointer back */
while ( t != NULL) /* convinated with inner loop, this will lead to infinite loop */
{
for ( i = 0; i < 10; i++) /* you may want to check if t != NULL here for safety */
{
/* not invalid but odd program that print the 4th element again and again */
if (count == 3)
{
printf("%d\n", t->item);
continue;
}
t = t->next;
count++;
}
}
}

Resources