Using void pointer to simulate a generic linkedlist in C - c

I'm new to C, and I think there may be an issue with pointers here. Any help would be appreciated!
I have a linkedlist struct that looks like this:
ll.h:
#ifndef LLTEST_LL_H
#define LLTEST_LL_H
#include <stdlib.h>
typedef struct _listNode {
void *data;
struct _listNode *next;
} listNode;
typedef struct {
int logicalLength;
int elementSize;
listNode *head;
listNode *tail;
} linkedlist;
typedef struct table {
const char* name;
size_t col_count;
size_t length;
} table;
typedef struct db {
const char* name;
size_t table_count;
table** tables;
} db;
void list_append(linkedlist *list, void *element);
void create_list(linkedlist *list, int elementSize);
void create_db(const char* db_name, db** db);
#endif //LLTEST_LL_H
main.c
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include "ll.h"
linkedlist databases_list;
void create_list(linkedlist *list, int elementSize)
{
list->logicalLength = 0;
list->elementSize = elementSize;
list->head = NULL;
list->tail = NULL;
}
void list_append(linkedlist *list, void *element)
{
listNode *node = malloc(sizeof(listNode));
node->data = malloc(list->elementSize);
node->next = NULL;
memcpy(node->data, element, list->elementSize);
if(list->logicalLength == 0) {
list->head = list->tail = node;
} else {
list->tail->next = node;
list->tail = node;
}
list->logicalLength++;
}
listNode* find_database_node(char *name){
listNode *node = databases_list.head;
//bool result = true;
listNode *found_node = NULL;
while(node != NULL) {
db *item = (db *)node->data;
if (strcmp(item->name, name) == 0){
found_node = node;
break;
}
node = node->next;
}
return found_node;
}
void get_db_pool(char *name, db *value){
listNode *node = find_database_node(name);
if(node != NULL){
value = (db *)node->data;
}
else{
value = NULL;
}
}
void set_db_pool(db* value){
list_append(&databases_list, (void *)value);
}
void create_db(const char* db_name, db** db) {
if (*db == NULL) {
*db = malloc(sizeof(db));
}
(*db)->name = db_name;
(*db)->table_count = 0;
(*db)->tables = NULL;
}
int main() {
create_list(&databases_list, sizeof(db *));
char* db_name= "mydb";
db* db1 = NULL;
create_db(db_name, &db1);
set_db_pool(db1); //<--this line
return 0;
}
On the line that I have marked "<--this line", when I check (db)databases_list.head->data's name parameter, I see "\222\017" instead of "mydb" as I would expect (such as when I check db1->name). What am I doing wrong?

I've taken the revised code and edited a bit to suit some of my prejudices, so my line numbers are probably slightly different from yours. When I run it under valgrind, I get a complaint:
==55831== Invalid write of size 8
==55831== at 0x100000EC7: main (ll17.c:78)
==55831== Address 0x100a7c350 is 8 bytes after a block of size 8 alloc'd
==55831== at 0x1000066F1: malloc (vg_replace_malloc.c:303)
==55831== by 0x100000EB9: main (ll17.c:73)
==55831==
==55831== Invalid write of size 8
==55831== at 0x100000ECF: main (ll17.c:78)
==55831== Address 0x100a7c348 is 0 bytes after a block of size 8 alloc'd
==55831== at 0x1000066F1: malloc (vg_replace_malloc.c:303)
==55831== by 0x100000EB9: main (ll17.c:73)
Line 73 is as shown:
void create_db(const char* db_name, db** db) {
if (*db == NULL) {
*db = malloc(sizeof(db)); // 73
}
This allocates enough space for a pointer (strictly, a pointer to a pointer), not for a db structure.
You should avoid using variables with the same name as their (base) type — it confuses everyone except the compiler.
You really need:
void create_db(const char* db_name, db** db) {
if (*db == NULL) {
*db = malloc(sizeof(**db));
}
With that change in place, the code runs OK under valgrind. According to my build of valgrind, it leaks a lot, but I've recently upgraded from Mac OS X 10.10 Yosemite to 10.11 El Capitan, and I don't trust my suppressions file to give me any useful information. It was built under Yosemite, and I'm also getting 'unknown fcntl calls' tracked by valgrind.

I think the line int your test code right here might be flawed.
create_list(&databases_list, sizeof(db *), NULL);
when you do sizeof(db *) you are actually getting the size of the pointer NOT the db struct. You should actually be doing sizeof(db). Since the element size only gets set to the size of a pointer you don't copy enough data over and when you read back you read corrupted data from memory causing your incorrect values.

Related

Hashing of small dictionary

I want to hash small dictionary ("dictionaries/small"). Main file compiles correctly, but at runtime it produces "Segmentation fault" message with function insert() (specifically something wrong with malloc(), but I don`t know what).
HASH.c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>
typedef struct node
{
char* name;
struct node* next;
}
node;
node* first[26] = {NULL};
int hash(const char* buffer)
{
return tolower(buffer[0]) - 'a';
}
void insert(int key, const char* buffer)
{
node* newptr = malloc(sizeof(node));
if (newptr == NULL)
{
return;
}
strcpy(newptr->name, buffer);
newptr->next = NULL;
if (first[key] == NULL)
{
first[key] = newptr;
}
else
{
node* predptr = first[key];
while (true)
{
if (predptr->next == NULL)
{
predptr->next = newptr;
break;
}
predptr = predptr->next;
}
}
}
In function insert() you correctly allocate the new node:
node* newptr = malloc(sizeof(node));
In this way you make room for a full struct node: a pointer to node and a pointer to char. But you don't allocate the space where those pointer are supposed to point.
So, when you copy the input buffer within name field, you are performing an illegal attempt to write to a char * pointer that has not been allocated and not even initialized:
strcpy(newptr->name, buffer);
All pointers need to be allocated (or at least initialized to a valid memory location) before writing in them. In your case:
newptr->name = malloc( strlen( buffer ) + 1 );
if( newptr->name )
{
strcpy(newptr->name, buffer);
}

Why am I getting Segmentation fault (core dumped) or bus error (core dumped) when trying to populate a struct?

So I am trying to use a pointer to a struct of MonsterAttacks as the data that belongs to an element of a linked list. In order to do this I try to populate a struct of MonsterAttacks and then pass that along with a null ptr to a next node to a function called create. However somewhere in the populate method a segmentation fault error occurs. I am working with three files list_demo.c, linked_list.h and linked_list.c. I will build all the the functions that make up a fully functioning linked list, well hoping I can as soon as I get pass this error. Been dealing with this error for about two days and I showed my professor and he could not figure out why its happening, it seems to come from the populate function. I have tried to return a pointer to a strut in which case I get a bus error, and I have tried almost every variation of getting input and storing it on the strut. I even deleted the function and tried to populate it in main, but nothing works. I am new to C and my professor helped me out for about an hour debug this problem and he finally gave up, so any help would be appreciated.
list_demo.c
#include <stdio.h>
#include "linked_list.h"
#include <stdlib.h>
void populate(struct MonsterAttacks *m){
printf("Enter the name for the Monster \n");
scanf("%40s",m->monsterName);
puts("What is his/her attack location?");
scanf("%40s",m->attackLocation);
puts("What are the number of victims this monster has demolished?");
scanf("%ud", &m->numOfVictims);
m->attackID = 0;
}
int main(void)
{
node* tmp = NULL;
struct MonsterAttacks *tmpMonst = (struct MonsterAttacks *)
malloc(sizeof(struct MonsterAttacks));
if(tmpMonst == NULL){
printf("Error allocating memory");
}
else
populate(tmpMonst);
node *head = create(tmpMonst,tmp);
free(tmpMonst);
return 0;
}
linked_list.h
#ifndef LINKED_LIST
#define LINKED_LIST
typedef struct node{
struct MonsterAttacks *monsterAttack;
struct node* next;
} node;
struct MonsterAttacks{
unsigned int attackID;
char monsterName[41];
char attackLocation[41];
unsigned int numOfVictims;
};
/*
create a new node
initialize the data and next field
return the newly created node
*/
node* create(struct MonsterAttacks *m,node* next);
#endif
linked_list.c
// from zentut.com, heavily adapted
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "linked_list.h"
/*
create a new node
initialize the data and next field
return the newly created node
*/
node* create(struct MonsterAttacks *m,node* next)
{
node* new_node = (node*)malloc(sizeof(node));
if(new_node == NULL)
{
printf("Error creating a new node.\n");
exit(0);
}
new_node->monsterAttack->attackID = 0;
new_node->next = next;
strncpy(new_node->monsterAttack->monsterName,m->monsterName,41);
strncpy(new_node->monsterAttack->attackLocation, m->attackLocation, 41);
new_node->monsterAttack->numOfVictims = m->numOfVictims;
return new_node;
}
Btw running on Red Hat using gcc compiler
new_node->monsterAttack->attackID = 0;
Allocating memory for new_node does not allocate memory for the MonsterAttacks struct inside it. That is why dereferencing monsterAttack to get its attackID is causing a seg fault.
A minimal working code
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
// Moved the two structs out to make a minimal reproducible code
/* #include "linked_list.h" */
struct MonsterAttacks{
unsigned int attackID;
char monsterName[41];
char attackLocation[41];
unsigned int numOfVictims;
};
typedef struct node{
struct MonsterAttacks *monsterAttack;
struct node* next;
} node;
void populate(struct MonsterAttacks *m){
printf("Enter the name for the Monster \n");
scanf("%40s",m->monsterName);
puts("What is his/her attack location?");
scanf("%40s",m->attackLocation);
puts("What are the number of victims this monster has demolished?");
scanf("%ud", &m->numOfVictims);
m->attackID = 0;
}
node* create(struct MonsterAttacks *m,node* next)
{
node* new_node = (node*)malloc(sizeof(node));
if(new_node == NULL)
{
printf("Error creating a new node.\n");
exit(0);
}
// Just add this line
new_node->monsterAttack = malloc(sizeof (struct MonsterAttacks));
new_node->monsterAttack->attackID = 0;
new_node->next = next;
strncpy(new_node->monsterAttack->monsterName,m->monsterName,41);
strncpy(new_node->monsterAttack->attackLocation, m->attackLocation, 41);
new_node->monsterAttack->numOfVictims = m->numOfVictims;
return new_node;
}
int main(void)
{
node* tmp = NULL;
struct MonsterAttacks *tmpMonst = (struct MonsterAttacks *)
malloc(sizeof(struct MonsterAttacks));
if(tmpMonst == NULL){
printf("Error allocating memory");
}
else {
populate(tmpMonst);
}
node *head = create(tmpMonst,tmp);
printf("Name: %s\n", tmpMonst->monsterName);
printf("num victim: %d\n", tmpMonst->numOfVictims);
free(tmpMonst);
return 0;
}
When you allocate memory for new_node in create(...), you allocate memory on the heap for a structure of type node to hold all the variables it contains. In this case, monsterAttack in node is initially a pointer to a struct that is pointing to nowhere. You need to explicitly allocate memory for the monsterAttack pointer to point to.
Edit: #bruceg pointed out the lack of semicolon, this malloc isn't the issue. #lightalchemist have highlighted that the second one is the fault.
struct MonsterAttacks *tmpMonst = (struct MonsterAttacks *);
malloc(sizeof(struct MonsterAttacks));
Your malloc call is wrong, malloc allocates and returns a pointer to the memory. You ignore/discard the pointer value.
Later code seems to assume that tmpMonst points to this allocated memory but there is no link between the two.
Try struct MonsterAttacks *tmpMonst = malloc(sizeof(struct MonsterAttacks));

My malloc doesn't update the heap properly

I'm trying to implement my own malloc and then test it by dumping the heap to see what I've managed to accomplish. It compiles fine but when I run it, I get the output of
head->[1:0:8]->NULL
this is a test program
after which it promptly crashes. It looks like the way I implemented my malloc, it is able to allocate the space for *this and *is, but that's all. Anyone have any ideas why this might be?
My main.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#define MALLOC(n) my_malloc(n)
#define DUMP_HEAP() dump_heap()
void* my_malloc(int);
int main()
{
char *this = MALLOC(5);
char *is = MALLOC(3);
char *a = MALLOC(2);
char *test = MALLOC(5);
DUMP_HEAP();
strcpy(this, "this");
strcpy(is, "is");
strcpy(a, "a");
strcpy(test, "test");
strcpy(program, "program");
printf("%s %s %s %s %s\n", this, is, a, test, program);
DUMP_HEAP();
return 0;
}
My malloc.c
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <assert.h>
struct Block
{
int occ;
int size;
struct Block *prev;
struct Block *next;
};
static struct Block *head = NULL;
void *my_malloc(int size)
{
void *pointer;
pointer = (void*)sbrk(size);
if(head == NULL)
{
head = pointer;
head->occ = 1;
head->prev=NULL;
head->next=NULL;
head->size = size;
return (void*)head+sizeof(struct Block);
}
else
{
struct Block* new ;
new = pointer;
head->next = new;
new->size = size;
new->occ = 1;
new->prev = head;
new->next = NULL;
head = new;
return (void*)new+sizeof(struct Block);
}
}
void dump_heap()
{
struct Block *cur;
printf("head->");
for(cur = head; cur != NULL; cur = cur->next)
{
printf("[%d:%d:%d]->", cur->occ, (char*)cur - (char*)head, cur->size);
assert((char*)cur >= (char*)head && (char*)cur + cur->size < (char*)sbrk(0));
if(cur->next != NULL) assert(cur->next->prev == cur);
}
printf("NULL\n");
}
You aren't accounting for the size of the Block struct when asking the system for memory.
Compare this line:
pointer = (void*)sbrk(size);
to how you're attempting to account for the struct later:
return (void*)head+sizeof(struct Block);
You should be accounting for the size of the Block in the sbrk call:
pointer = (void*)sbrk(size + sizeof(struct Block));
Also, as has been pointed out, you should not do pointer arithmetic on void*. So your return statements should leave the head pointer uncasted and just add 1 to account for the block size:
return (void*)(head + 1);
Also also, upon further discussion it is clear that head is being used as the tail of the linked list. This introduces a bug in dump_heap. You may want to rename head to tail and maintain a proper head, one which only ever changes in malloc when it was previously NULL.

How to return a node in a list in C

I have a requirement to implement two functions
directed_by(node_t * list, char * director)
rated(node_t * list, const rating_t rating)
Each will require I pass in a list and iterate through it. I'm new to C and actually I'm not that familiar with list structures either. Can someone please help me understand how do I return a list so that I can pass into my two functions so that I can iterate through each list?
Here is my code so far. I think I need to return something in my add_movie() function, such as node_t, but I'm not sure how to do that?
LIST.H
#ifndef BASICLIST_H_
#define BASICLIST_H_
typedef struct node {
void * data; /* pointer to data */
struct node * next; /* pointer to next next node */
} node_t;
int list_add(node_t ** list, void * data);
#endif
MOVIE.H
#include <stdio.h>
#ifndef MOVIE_H
#define MOVIE_H
#define SIZE_LIMIT 25
#define RATING_SIZE 6
typedef struct {
char title[SIZE_LIMIT];
char director[SIZE_LIMIT];
char rating[RATING_SIZE];
//rating_t rating;
int year;
}movie_t;
void get_movie(movie_t * movie);
void print_movie(const movie_t *m);
void print_movies(const movie_t *m);
void add_movie(movie_t movie);
#endif /* MOVIE_H */
LIST.C
#include <stdio.h>
#include <stdlib.h>
#include"basiclist.h"
int list_add(node_t ** list, void * data) {
int ret = 0;
node_t * newnode = (node_t *) malloc(sizeof(node_t));
if (newnode == NULL) {
ret = -1;
}
else {
newnode->data = data;
newnode->next = *list;
}
*list = newnode;
return ret;
}
MOVIE.C
#include <stdio.h>
#include <stdlib.h>
#include "movie.h"
#include "basiclist.h"
void print_movies(const movie_t *m) {
printf("%s\t%s\t%s\t%d\n", m->title, m->director, m->rating, m->year);
}
void add_movie(movie_t movie) {
node_t * list = NULL;
movie_t first_movie = movie;
movie_t * new_movie;
new_movie = malloc(sizeof (*new_movie));
*new_movie = first_movie;
list_add(&list, new_movie);
node_t * curr;
curr = list;
while (curr != NULL) {
print_movies(curr->data);
curr = curr->next;
}
}
MAIN.C
#include "movie.h"
#include <stdlib.h>
#include <stdio.h>
#include "basiclist.h"
int main(void) {
movie_t movie1 = {"Movie1", "Director1", "PG-13", 1900};
movie_t movie2 = {"Movie2", "Director2", "R", 1900};
movie_t movie3 = {"Movie3", "Director3", "G", 1900};
movie_t movie4 = {"Movie4", "Director4", "R", 1900};
add_movie(movie1);
add_movie(movie2);
add_movie(movie3);
add_movie(movie4);
/*undefined methods
directed_by(node_t * list, char * director)
rated(node_t * list, const rating_t rating)
*/
return 0;
}
The main problem with this code is that you are not returning or passing your list to the add_movie function.
In each call you are creating a new list and losing it's reference, so you can't use it.
The "easy" fix to your code would be to change:
void add_movie(movie_t movie)
to
void add_movie(node_t** list, movie_t movie);
and remove the first line of the function, then change your main to:
node_t* list = NULL;
add_movie(&list, movie1);
add_movie(&list, movie2);
add_movie(&list, movie3);
add_movie(&list, movie4);
With this change you will have the list with movie4, movie3, movie2 and movie1.
PS: you also want to change your list add method to return -1 instead of setting ret to -1. In its current form you would lose your list in case of an error because you are setting the given reference to NULL (also, that would create a memory leak).
PS 2: It is not really recommended to pass structs as arguments in C, you should use pointers instead. The reason is that when you pass a struct as argument C will copy its whole content to a temporary struct variable, so if you have, say, a 256 bytes struct you will be copying 256 bytes of information for every function call, instead of 4 (32 bits systems) or 8 (64 bits systems) if you had used a pointer.

All Nodes in a linked list point to same object

The problem is somewhere in here....
char buffer[80];
char *name;
while (1) {
fgets(buffer, 80, inf); //reads in at most 80 char from a line
if (feof(inf)) //this checks to see if the special EOF was read
break; //if so, break out of while and continue with your main
name = (char *) malloc(sizeof(char)*20);
....
name = strtok(buffer, " ");//get first token up to space
stock = newStock(name,...)
....
}
I'm working in C with generic linked lists. I made a list implementation that I've tested and know works with chars. I'm trying to add stocks (I created a stock struct) to the linked list, with each node of the linked list holding a stock struct, but when I finish reading in the stocks all of the nodes point to the same struct and I can't figure out why. Here's some snippets of my code
list *list = malloc(sizeof(list));
newList(list, sizeof(stock_t));
while(1) {
...
(read from file)
...
stock_t *stock;
stock = newStock(name, closes, opens, numshares, getPriceF, getTotalDollarAmountF,getPercentChangeF,toStringF);
addToBack(list, stock);
}
Here's the newStock function:
stock_t *newStock(char *name, float closingSharePrice, float openingSharePrice, int numberOfShares, getPrice getP, getTotalDollarAmount getTotal, getPercentChange getPercent, toString toStr) {
stock_t *stock = malloc(sizeof(stock));
stock->stockSymbol = name;
stock->closingSharePrice = closingSharePrice;
stock->openingSharePrice = openingSharePrice;
stock->numberOfShares = numberOfShares;
stock->getP = getP;
stock->getTotal = getTotal;
stock->getPercent = getPercent;
stock->toStr = toStr;
return stock;
}
In a way I see what's wrong. newStock returns a new pointer every time, but it always gets stored in the variable 'stock' which is what every node points to, so it's going to be equal to whatever the last pointer newStock returned was...but I don't see the way around this. I tried having newStock return just a stock_t, and doing addToBack(list, &stock), but that didn't solve the problem either.
Any help would be appreciated!
Here is some code from the list:
typedef struct node {
void *data;
struct node *next;
}node_t;
typedef struct {
int length;
int elementSize;
node_t *head;
node_t *tail;
} list;
void newList(list *list, int elementSize) {
assert(elementSize > 0);
list->length = 0;
list->elementSize = elementSize;
list->head = list->tail = NULL;
}
void addToBack(list *list, void *element) {
node_t *node = malloc(sizeof(node_t));
node->data = malloc(list->elementSize);
node->next = NULL; //back node
memcpy(node->data, element, list->elementSize);
if (list->length == 0) { //if first node added
list->head = list->tail = node;
}
else {
list->tail->next = node;
list->tail = node;
}
list->length++;
}
Here's code from the stock struct:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef float (*getPrice)(void *S);
typedef float (*getTotalDollarAmount)(void *S);
typedef float (*getPercentChange)(void *S);
typedef char *(*toString)(void *S);
typedef struct stock{
char *stockSymbol;
float closingSharePrice;
float openingSharePrice;
int numberOfShares;
getPrice getP;
getTotalDollarAmount getTotal;
getPercentChange getPercent;
toString toStr;
}stock_t;
The generic functions probably seem like overkill but this is for homework (if you couldn't tell already) so we were asked to specifically use them. I don't think that has anything to do with the problem though.
Here are the definitions for those functions anyway
float getPriceF(void *S) {
stock_t *stock = (stock_t*)S;
return stock->closingSharePrice;
}
float getTotalDollarAmountF(void *S) {
stock_t *stock = (stock_t*)S;
return ((stock->closingSharePrice) * (stock->numberOfShares));
}
float getPercentChangeF(void *S) {
stock_t *stock = (stock_t*)S;
return ((stock->closingSharePrice - stock->openingSharePrice)/(stock->openingSharePrice));
}
char *toStringF(void *S) {
stock_t* stock = (stock_t*)S;
char *name = malloc(20*sizeof(char));
//sprintf(name, "Symbol is: %s. ", (stock->stockSymbol));
return stock->stockSymbol;
}
void printStock(void *S) {
char *str = toStringF(S);
printf("%s \n", str);
}
And this is how I'm traversing the list:
typedef void (*iterate)(void *); //this is in the list.h file, just putting it here to avoid confusion
void traverse(list *list, iterate iterator) {
assert(iterator != NULL);
node_t *current = list->head;
while (current != NULL) {
iterator(current->data);
current = current->next;
}
}
And then in my main I just called
traverse(list, printStock);
I can't find any problems with your code (that would cause your problem, anyway - there are places where you don't check the return from malloc() and stuff like that, but those are not relevant to this question). You don't supply the definition of stock_t, so I made a new data struct, and a new couple of functions, otherwise I just copied and pasted the code you provided:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
/* Your code starts here */
typedef struct node {
void *data;
struct node *next;
}node_t;
typedef struct {
int length;
int elementSize;
node_t *head;
node_t *tail;
} list;
void newList(list *list, int elementSize) {
assert(elementSize > 0);
list->length = 0;
list->elementSize = elementSize;
list->head = list->tail = NULL;
}
void addToBack(list *list, void *element) {
node_t *node = malloc(sizeof(node_t));
node->data = malloc(list->elementSize);
node->next = NULL; //back node
memcpy(node->data, element, list->elementSize);
if (list->length == 0) { //if first node added
list->head = list->tail = node;
}
else {
list->tail->next = node;
list->tail = node;
}
list->length++;
}
/* Your code ends here */
/* I made a new struct, rather than stock, since you didn't supply it */
struct mydata {
int num1;
int num2;
};
/* I use this instead of newStock(), but it works the same way */
struct mydata * newNode(const int a, const int b) {
struct mydata * newdata = malloc(sizeof *newdata);
if ( newdata == NULL ) {
fputs("Error allocating memory", stderr);
exit(EXIT_FAILURE);
}
newdata->num1 = a;
newdata->num2 = b;
return newdata;
}
/* I added this function to check the list is good */
void printList(list * list) {
struct node * node = list->head;
int n = 1;
while ( node ) {
struct mydata * data = node->data;
printf("%d: %d %d\n", n++, data->num1, data->num2);
node = node->next;
}
}
/* Main function */
int main(void) {
list *list = malloc(sizeof(list));
newList(list, sizeof(struct mydata));
struct mydata * data;
data = newNode(1, 2);
addToBack(list, data);
data = newNode(3, 4);
addToBack(list, data);
data = newNode(5, 6);
addToBack(list, data);
printList(list);
return 0;
}
which outputs this:
paul#MacBook:~/Documents/src$ ./list
1: 1 2
2: 3 4
3: 5 6
paul#MacBook:~/Documents/src$
demonstrating that you have a 3 node list, with all nodes different and where you'd expect them to be.
Either there is some other problem in code you're not showing, or for some reason you are thinking each node points to the same struct when it actually doesn't.
One possibility is that you have a char * data member in your stock struct. It's impossible to tell from the code you provided, but it's possible that you really are creating different nodes, but they all end up pointing to the same name, so they just look like they're the same. If you're assigning a pointer to name, you should make sure it's freshly allocated memory each time, and that you're not just, for instance, strcpy()ing into the same memory and assigning the same address to each stock struct.
EDIT: Looks like that was your problem. This:
name = (char *) malloc(sizeof(char)*20);
....
name = strtok(buffer, " ");
should be:
name = (char *) malloc(sizeof(char)*20);
....
strcpy(name, strtok(buffer, " "));
Right now, you malloc() new memory and store a reference to it in name, but then you lose that reference and your memory when you overwrite it with the address returned from strtok(). Instead, you need to copy that token into your newly allocated memory, as shown.

Resources