Segmentation fault / list initializing












-1















I want to create a list with the following structure:




  • list.h: Contains function prototypes and defines data types

  • lt.c: main function to test the list

  • list.c: actual implementation of the list


When executing it I always get a segfault error. When trying to identify it with gdb it is shown that it is the fault of the following line in lt.c:



list_t *li=list_init();


The rest of my lt.c file looks as follows:



#include <stdio.h>
#include <stdlib.h>
#include "list.h"

int main ( int argc, char *argv [ ], char *envp [ ] )
{
list_t *li=list_init();
//li=list_init();
/* if((li=list_init())==NULL)
{
perror (" Cannot allocate memory" ) ;
exit(-1);
}*/
}


My implementation of the list.c function list_init() is as follows:



list_t *list_init ()
{
list_t* newlist = malloc(sizeof(*newlist));
if (!newlist)
{
perror ("malloc-newlist");
exit (EXIT_FAILURE);
}`enter code here`
//newlist->first=NULL;
//newlist->last=NULL;
newlist->first = (struct list_elem *) malloc(sizeof(struct list_elem));
newlist->last = (struct list_elem *) malloc(sizeof(struct list_elem));
return newlist;
}


My list.h file is as follows:



    struct list_elem {
struct list_elem *next; // Zeiger auf das naechste Element
char *data; // Zeiger auf ein Datenobject
};

typedef struct list {
struct list_elem *first;// erstes Element in der Liste
struct list_elem *last; // letztes Element in der Liste
} list_t;

/* function prototypes */
list_t *list_init ();


However, I do not know how I could change the implementation so that it does not occur anymore.
Thank you very much for your help.










share|improve this question

























  • Comments are not for extended discussion; this conversation has been moved to chat.

    – Samuel Liew
    Nov 25 '18 at 3:53
















-1















I want to create a list with the following structure:




  • list.h: Contains function prototypes and defines data types

  • lt.c: main function to test the list

  • list.c: actual implementation of the list


When executing it I always get a segfault error. When trying to identify it with gdb it is shown that it is the fault of the following line in lt.c:



list_t *li=list_init();


The rest of my lt.c file looks as follows:



#include <stdio.h>
#include <stdlib.h>
#include "list.h"

int main ( int argc, char *argv [ ], char *envp [ ] )
{
list_t *li=list_init();
//li=list_init();
/* if((li=list_init())==NULL)
{
perror (" Cannot allocate memory" ) ;
exit(-1);
}*/
}


My implementation of the list.c function list_init() is as follows:



list_t *list_init ()
{
list_t* newlist = malloc(sizeof(*newlist));
if (!newlist)
{
perror ("malloc-newlist");
exit (EXIT_FAILURE);
}`enter code here`
//newlist->first=NULL;
//newlist->last=NULL;
newlist->first = (struct list_elem *) malloc(sizeof(struct list_elem));
newlist->last = (struct list_elem *) malloc(sizeof(struct list_elem));
return newlist;
}


My list.h file is as follows:



    struct list_elem {
struct list_elem *next; // Zeiger auf das naechste Element
char *data; // Zeiger auf ein Datenobject
};

typedef struct list {
struct list_elem *first;// erstes Element in der Liste
struct list_elem *last; // letztes Element in der Liste
} list_t;

/* function prototypes */
list_t *list_init ();


However, I do not know how I could change the implementation so that it does not occur anymore.
Thank you very much for your help.










share|improve this question

























  • Comments are not for extended discussion; this conversation has been moved to chat.

    – Samuel Liew
    Nov 25 '18 at 3:53














-1












-1








-1








I want to create a list with the following structure:




  • list.h: Contains function prototypes and defines data types

  • lt.c: main function to test the list

  • list.c: actual implementation of the list


When executing it I always get a segfault error. When trying to identify it with gdb it is shown that it is the fault of the following line in lt.c:



list_t *li=list_init();


The rest of my lt.c file looks as follows:



#include <stdio.h>
#include <stdlib.h>
#include "list.h"

int main ( int argc, char *argv [ ], char *envp [ ] )
{
list_t *li=list_init();
//li=list_init();
/* if((li=list_init())==NULL)
{
perror (" Cannot allocate memory" ) ;
exit(-1);
}*/
}


My implementation of the list.c function list_init() is as follows:



list_t *list_init ()
{
list_t* newlist = malloc(sizeof(*newlist));
if (!newlist)
{
perror ("malloc-newlist");
exit (EXIT_FAILURE);
}`enter code here`
//newlist->first=NULL;
//newlist->last=NULL;
newlist->first = (struct list_elem *) malloc(sizeof(struct list_elem));
newlist->last = (struct list_elem *) malloc(sizeof(struct list_elem));
return newlist;
}


My list.h file is as follows:



    struct list_elem {
struct list_elem *next; // Zeiger auf das naechste Element
char *data; // Zeiger auf ein Datenobject
};

typedef struct list {
struct list_elem *first;// erstes Element in der Liste
struct list_elem *last; // letztes Element in der Liste
} list_t;

/* function prototypes */
list_t *list_init ();


However, I do not know how I could change the implementation so that it does not occur anymore.
Thank you very much for your help.










share|improve this question
















I want to create a list with the following structure:




  • list.h: Contains function prototypes and defines data types

  • lt.c: main function to test the list

  • list.c: actual implementation of the list


When executing it I always get a segfault error. When trying to identify it with gdb it is shown that it is the fault of the following line in lt.c:



list_t *li=list_init();


The rest of my lt.c file looks as follows:



#include <stdio.h>
#include <stdlib.h>
#include "list.h"

int main ( int argc, char *argv [ ], char *envp [ ] )
{
list_t *li=list_init();
//li=list_init();
/* if((li=list_init())==NULL)
{
perror (" Cannot allocate memory" ) ;
exit(-1);
}*/
}


My implementation of the list.c function list_init() is as follows:



list_t *list_init ()
{
list_t* newlist = malloc(sizeof(*newlist));
if (!newlist)
{
perror ("malloc-newlist");
exit (EXIT_FAILURE);
}`enter code here`
//newlist->first=NULL;
//newlist->last=NULL;
newlist->first = (struct list_elem *) malloc(sizeof(struct list_elem));
newlist->last = (struct list_elem *) malloc(sizeof(struct list_elem));
return newlist;
}


My list.h file is as follows:



    struct list_elem {
struct list_elem *next; // Zeiger auf das naechste Element
char *data; // Zeiger auf ein Datenobject
};

typedef struct list {
struct list_elem *first;// erstes Element in der Liste
struct list_elem *last; // letztes Element in der Liste
} list_t;

/* function prototypes */
list_t *list_init ();


However, I do not know how I could change the implementation so that it does not occur anymore.
Thank you very much for your help.







c






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 23 '18 at 7:25







SQLLearner

















asked Nov 23 '18 at 4:46









SQLLearnerSQLLearner

85




85













  • Comments are not for extended discussion; this conversation has been moved to chat.

    – Samuel Liew
    Nov 25 '18 at 3:53



















  • Comments are not for extended discussion; this conversation has been moved to chat.

    – Samuel Liew
    Nov 25 '18 at 3:53

















Comments are not for extended discussion; this conversation has been moved to chat.

– Samuel Liew
Nov 25 '18 at 3:53





Comments are not for extended discussion; this conversation has been moved to chat.

– Samuel Liew
Nov 25 '18 at 3:53












2 Answers
2






active

oldest

votes


















1














While it is impossible to tell where your problem lies exactly, I suspect it lies in one of two places. One, you are initializing each data member with a string literal which is read-only on all but a very few systems. So if anywhere in your code you attempt to modify data you could expect a SegFault. The same would apply if you later attempt to free (pointer->data);



Two, you fail of assign your node->next pointers correctly leading to your traversal attempting to derefernce a NULL pointer or indeterminate pointer leading to the same SegFault. This can occur if your append function fails to handle the if (!list->first) { ... } case correctly or the else case where you will be required to set pointer->next = newnode;



There is really no way to tell unless you post a A Minimal, Complete, and Verifiable Example (MCVE), but given list operations are somewhat generic, you could correct the shortcomings with something similar to the following for your init() and append() functions (with an added print() and free() functions thrown in for good measure), e.g.



#include <stdio.h>
#include <stdlib.h>

struct list_elem {
struct list_elem *next; // Zeiger auf das naechste Element
char *data; // Zeiger auf ein Datenobject
};

typedef struct list {
struct list_elem *first;// erstes Element in der Liste
struct list_elem *last; // letztes Element in der Liste
} list_t;

/* function prototypes */
list_t *list_init ();
struct list_elem *list_append (list_t *list, char *data);
void list_print (list_t *list);
void list_free (list_t *list);

int main (void)
{
list_t *li = list_init();

if (list_append (li, (char){"erstes"}) == NULL ||
list_append (li, (char){"zweites"}) == NULL ||
list_append (li, (char){"drittes"}) == NULL) {
perror ("Cannot allocate memory" ) ;
exit (EXIT_FAILURE);
}

list_print (li);
list_free (li);

exit (EXIT_SUCCESS);
}

list_t *list_init (void)
{
list_t *newlist = malloc (sizeof *newlist);

if (!newlist) {
perror ("malloc-newlist");
exit (EXIT_FAILURE);
}

newlist->first = NULL;
newlist->last = NULL;

return newlist;
}

struct list_elem *list_append (list_t *list, char *data)
{
struct list_elem *node = NULL;

if (!list)
return NULL;

if (!(node = malloc (sizeof *node))) {
perror ("malloc-node");
return NULL;
}
node->data = data;
node->next = NULL;

if (!list->first)
list->first = node;
else {
struct list_elem *iter = list->first;
while (iter->next)
iter = iter->next;
iter->next = node;
}

return (list->last = node);
}

void list_print (list_t *list)
{
struct list_elem *iter = NULL;

if (!list)
return;

iter = list->first;

while (iter) {
printf ("%sn", iter->data);
iter = iter->next;
}
}

void list_free (list_t *list)
{
struct list_elem *iter = NULL;

if (!list)
return;

iter = list->first;

while (iter) {
struct list_elem *victim = iter;
iter = iter->next;
free (victim);
}

free (list);
}


Example Use/Output



$ ./bin/ll_list_elem
erstes
zweites
drittes


Memory Use/Error Check



There is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?



In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.



It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.



For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.



$ valgrind ./bin/ll_list_elem
==22383== Memcheck, a memory error detector
==22383== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==22383== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==22383== Command: ./bin/ll_list_elem
==22383==
erstes
zweites
drittes
==22383==
==22383== HEAP SUMMARY:
==22383== in use at exit: 0 bytes in 0 blocks
==22383== total heap usage: 4 allocs, 4 frees, 64 bytes allocated
==22383==
==22383== All heap blocks were freed -- no leaks are possible
==22383==
==22383== For counts of detected and suppressed errors, rerun with: -v
==22383== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)


Always confirm that you have freed all memory you have allocated and that there are no memory errors.



Using last pointer with Forward-Chaining



Since you have a last pointer there is no need for a generic iteration of the list to find the last pointer. I suspect you are intending to use forward-chaining. In that case, you can simply modify append() as follows:



    if (!list->first)
list->first = node;
else
list->last->next = node;


(note: the list->last = node assignment is handled in the return)






share|improve this answer


























  • I suspect you are correct -- added an example of forward-chaining with last.

    – David C. Rankin
    Nov 23 '18 at 7:13











  • Thank you for your answer. You have written: "You are initializing each data member with a string literal which is read-only on all but a very few systems.". -> How can I change that?

    – SQLLearner
    Nov 23 '18 at 7:34











  • Look how I used a "Compound Literal" to cast the string literals to (char ){...} making them an array of char (which you can change -- but not make longer). Note: the compound literal is only available C99+ or by specific compiler extension.

    – David C. Rankin
    Nov 23 '18 at 7:45



















0














i think you are not allocate memory in proper way.



TList *list_init()
{
TList *newList = (TList *) malloc(sizeof(TList));

newList->first = (struct list_elem *) malloc(sizeof(structlist_elem));
newList->last = (struct list_elem *) malloc(sizeof(struct list_elem));

newList->first->next= NULL;
newList->last->next= NULL;

return newList;
}





share|improve this answer
























  • This code is weird, there are typos, the types are not the same as in the question and it doesn't answer the question at all.

    – Jabberwocky
    Nov 23 '18 at 7:05








  • 1





    Allocating for first and last in init() will greatly complicate your append() function. (not to mention updating last)

    – David C. Rankin
    Nov 23 '18 at 7:05













  • @Jabberwocky , because we don't have enough information of list append.

    – raka
    Nov 23 '18 at 7:10











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53440775%2fsegmentation-fault-list-initializing%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














While it is impossible to tell where your problem lies exactly, I suspect it lies in one of two places. One, you are initializing each data member with a string literal which is read-only on all but a very few systems. So if anywhere in your code you attempt to modify data you could expect a SegFault. The same would apply if you later attempt to free (pointer->data);



Two, you fail of assign your node->next pointers correctly leading to your traversal attempting to derefernce a NULL pointer or indeterminate pointer leading to the same SegFault. This can occur if your append function fails to handle the if (!list->first) { ... } case correctly or the else case where you will be required to set pointer->next = newnode;



There is really no way to tell unless you post a A Minimal, Complete, and Verifiable Example (MCVE), but given list operations are somewhat generic, you could correct the shortcomings with something similar to the following for your init() and append() functions (with an added print() and free() functions thrown in for good measure), e.g.



#include <stdio.h>
#include <stdlib.h>

struct list_elem {
struct list_elem *next; // Zeiger auf das naechste Element
char *data; // Zeiger auf ein Datenobject
};

typedef struct list {
struct list_elem *first;// erstes Element in der Liste
struct list_elem *last; // letztes Element in der Liste
} list_t;

/* function prototypes */
list_t *list_init ();
struct list_elem *list_append (list_t *list, char *data);
void list_print (list_t *list);
void list_free (list_t *list);

int main (void)
{
list_t *li = list_init();

if (list_append (li, (char){"erstes"}) == NULL ||
list_append (li, (char){"zweites"}) == NULL ||
list_append (li, (char){"drittes"}) == NULL) {
perror ("Cannot allocate memory" ) ;
exit (EXIT_FAILURE);
}

list_print (li);
list_free (li);

exit (EXIT_SUCCESS);
}

list_t *list_init (void)
{
list_t *newlist = malloc (sizeof *newlist);

if (!newlist) {
perror ("malloc-newlist");
exit (EXIT_FAILURE);
}

newlist->first = NULL;
newlist->last = NULL;

return newlist;
}

struct list_elem *list_append (list_t *list, char *data)
{
struct list_elem *node = NULL;

if (!list)
return NULL;

if (!(node = malloc (sizeof *node))) {
perror ("malloc-node");
return NULL;
}
node->data = data;
node->next = NULL;

if (!list->first)
list->first = node;
else {
struct list_elem *iter = list->first;
while (iter->next)
iter = iter->next;
iter->next = node;
}

return (list->last = node);
}

void list_print (list_t *list)
{
struct list_elem *iter = NULL;

if (!list)
return;

iter = list->first;

while (iter) {
printf ("%sn", iter->data);
iter = iter->next;
}
}

void list_free (list_t *list)
{
struct list_elem *iter = NULL;

if (!list)
return;

iter = list->first;

while (iter) {
struct list_elem *victim = iter;
iter = iter->next;
free (victim);
}

free (list);
}


Example Use/Output



$ ./bin/ll_list_elem
erstes
zweites
drittes


Memory Use/Error Check



There is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?



In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.



It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.



For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.



$ valgrind ./bin/ll_list_elem
==22383== Memcheck, a memory error detector
==22383== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==22383== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==22383== Command: ./bin/ll_list_elem
==22383==
erstes
zweites
drittes
==22383==
==22383== HEAP SUMMARY:
==22383== in use at exit: 0 bytes in 0 blocks
==22383== total heap usage: 4 allocs, 4 frees, 64 bytes allocated
==22383==
==22383== All heap blocks were freed -- no leaks are possible
==22383==
==22383== For counts of detected and suppressed errors, rerun with: -v
==22383== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)


Always confirm that you have freed all memory you have allocated and that there are no memory errors.



Using last pointer with Forward-Chaining



Since you have a last pointer there is no need for a generic iteration of the list to find the last pointer. I suspect you are intending to use forward-chaining. In that case, you can simply modify append() as follows:



    if (!list->first)
list->first = node;
else
list->last->next = node;


(note: the list->last = node assignment is handled in the return)






share|improve this answer


























  • I suspect you are correct -- added an example of forward-chaining with last.

    – David C. Rankin
    Nov 23 '18 at 7:13











  • Thank you for your answer. You have written: "You are initializing each data member with a string literal which is read-only on all but a very few systems.". -> How can I change that?

    – SQLLearner
    Nov 23 '18 at 7:34











  • Look how I used a "Compound Literal" to cast the string literals to (char ){...} making them an array of char (which you can change -- but not make longer). Note: the compound literal is only available C99+ or by specific compiler extension.

    – David C. Rankin
    Nov 23 '18 at 7:45
















1














While it is impossible to tell where your problem lies exactly, I suspect it lies in one of two places. One, you are initializing each data member with a string literal which is read-only on all but a very few systems. So if anywhere in your code you attempt to modify data you could expect a SegFault. The same would apply if you later attempt to free (pointer->data);



Two, you fail of assign your node->next pointers correctly leading to your traversal attempting to derefernce a NULL pointer or indeterminate pointer leading to the same SegFault. This can occur if your append function fails to handle the if (!list->first) { ... } case correctly or the else case where you will be required to set pointer->next = newnode;



There is really no way to tell unless you post a A Minimal, Complete, and Verifiable Example (MCVE), but given list operations are somewhat generic, you could correct the shortcomings with something similar to the following for your init() and append() functions (with an added print() and free() functions thrown in for good measure), e.g.



#include <stdio.h>
#include <stdlib.h>

struct list_elem {
struct list_elem *next; // Zeiger auf das naechste Element
char *data; // Zeiger auf ein Datenobject
};

typedef struct list {
struct list_elem *first;// erstes Element in der Liste
struct list_elem *last; // letztes Element in der Liste
} list_t;

/* function prototypes */
list_t *list_init ();
struct list_elem *list_append (list_t *list, char *data);
void list_print (list_t *list);
void list_free (list_t *list);

int main (void)
{
list_t *li = list_init();

if (list_append (li, (char){"erstes"}) == NULL ||
list_append (li, (char){"zweites"}) == NULL ||
list_append (li, (char){"drittes"}) == NULL) {
perror ("Cannot allocate memory" ) ;
exit (EXIT_FAILURE);
}

list_print (li);
list_free (li);

exit (EXIT_SUCCESS);
}

list_t *list_init (void)
{
list_t *newlist = malloc (sizeof *newlist);

if (!newlist) {
perror ("malloc-newlist");
exit (EXIT_FAILURE);
}

newlist->first = NULL;
newlist->last = NULL;

return newlist;
}

struct list_elem *list_append (list_t *list, char *data)
{
struct list_elem *node = NULL;

if (!list)
return NULL;

if (!(node = malloc (sizeof *node))) {
perror ("malloc-node");
return NULL;
}
node->data = data;
node->next = NULL;

if (!list->first)
list->first = node;
else {
struct list_elem *iter = list->first;
while (iter->next)
iter = iter->next;
iter->next = node;
}

return (list->last = node);
}

void list_print (list_t *list)
{
struct list_elem *iter = NULL;

if (!list)
return;

iter = list->first;

while (iter) {
printf ("%sn", iter->data);
iter = iter->next;
}
}

void list_free (list_t *list)
{
struct list_elem *iter = NULL;

if (!list)
return;

iter = list->first;

while (iter) {
struct list_elem *victim = iter;
iter = iter->next;
free (victim);
}

free (list);
}


Example Use/Output



$ ./bin/ll_list_elem
erstes
zweites
drittes


Memory Use/Error Check



There is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?



In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.



It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.



For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.



$ valgrind ./bin/ll_list_elem
==22383== Memcheck, a memory error detector
==22383== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==22383== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==22383== Command: ./bin/ll_list_elem
==22383==
erstes
zweites
drittes
==22383==
==22383== HEAP SUMMARY:
==22383== in use at exit: 0 bytes in 0 blocks
==22383== total heap usage: 4 allocs, 4 frees, 64 bytes allocated
==22383==
==22383== All heap blocks were freed -- no leaks are possible
==22383==
==22383== For counts of detected and suppressed errors, rerun with: -v
==22383== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)


Always confirm that you have freed all memory you have allocated and that there are no memory errors.



Using last pointer with Forward-Chaining



Since you have a last pointer there is no need for a generic iteration of the list to find the last pointer. I suspect you are intending to use forward-chaining. In that case, you can simply modify append() as follows:



    if (!list->first)
list->first = node;
else
list->last->next = node;


(note: the list->last = node assignment is handled in the return)






share|improve this answer


























  • I suspect you are correct -- added an example of forward-chaining with last.

    – David C. Rankin
    Nov 23 '18 at 7:13











  • Thank you for your answer. You have written: "You are initializing each data member with a string literal which is read-only on all but a very few systems.". -> How can I change that?

    – SQLLearner
    Nov 23 '18 at 7:34











  • Look how I used a "Compound Literal" to cast the string literals to (char ){...} making them an array of char (which you can change -- but not make longer). Note: the compound literal is only available C99+ or by specific compiler extension.

    – David C. Rankin
    Nov 23 '18 at 7:45














1












1








1







While it is impossible to tell where your problem lies exactly, I suspect it lies in one of two places. One, you are initializing each data member with a string literal which is read-only on all but a very few systems. So if anywhere in your code you attempt to modify data you could expect a SegFault. The same would apply if you later attempt to free (pointer->data);



Two, you fail of assign your node->next pointers correctly leading to your traversal attempting to derefernce a NULL pointer or indeterminate pointer leading to the same SegFault. This can occur if your append function fails to handle the if (!list->first) { ... } case correctly or the else case where you will be required to set pointer->next = newnode;



There is really no way to tell unless you post a A Minimal, Complete, and Verifiable Example (MCVE), but given list operations are somewhat generic, you could correct the shortcomings with something similar to the following for your init() and append() functions (with an added print() and free() functions thrown in for good measure), e.g.



#include <stdio.h>
#include <stdlib.h>

struct list_elem {
struct list_elem *next; // Zeiger auf das naechste Element
char *data; // Zeiger auf ein Datenobject
};

typedef struct list {
struct list_elem *first;// erstes Element in der Liste
struct list_elem *last; // letztes Element in der Liste
} list_t;

/* function prototypes */
list_t *list_init ();
struct list_elem *list_append (list_t *list, char *data);
void list_print (list_t *list);
void list_free (list_t *list);

int main (void)
{
list_t *li = list_init();

if (list_append (li, (char){"erstes"}) == NULL ||
list_append (li, (char){"zweites"}) == NULL ||
list_append (li, (char){"drittes"}) == NULL) {
perror ("Cannot allocate memory" ) ;
exit (EXIT_FAILURE);
}

list_print (li);
list_free (li);

exit (EXIT_SUCCESS);
}

list_t *list_init (void)
{
list_t *newlist = malloc (sizeof *newlist);

if (!newlist) {
perror ("malloc-newlist");
exit (EXIT_FAILURE);
}

newlist->first = NULL;
newlist->last = NULL;

return newlist;
}

struct list_elem *list_append (list_t *list, char *data)
{
struct list_elem *node = NULL;

if (!list)
return NULL;

if (!(node = malloc (sizeof *node))) {
perror ("malloc-node");
return NULL;
}
node->data = data;
node->next = NULL;

if (!list->first)
list->first = node;
else {
struct list_elem *iter = list->first;
while (iter->next)
iter = iter->next;
iter->next = node;
}

return (list->last = node);
}

void list_print (list_t *list)
{
struct list_elem *iter = NULL;

if (!list)
return;

iter = list->first;

while (iter) {
printf ("%sn", iter->data);
iter = iter->next;
}
}

void list_free (list_t *list)
{
struct list_elem *iter = NULL;

if (!list)
return;

iter = list->first;

while (iter) {
struct list_elem *victim = iter;
iter = iter->next;
free (victim);
}

free (list);
}


Example Use/Output



$ ./bin/ll_list_elem
erstes
zweites
drittes


Memory Use/Error Check



There is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?



In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.



It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.



For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.



$ valgrind ./bin/ll_list_elem
==22383== Memcheck, a memory error detector
==22383== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==22383== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==22383== Command: ./bin/ll_list_elem
==22383==
erstes
zweites
drittes
==22383==
==22383== HEAP SUMMARY:
==22383== in use at exit: 0 bytes in 0 blocks
==22383== total heap usage: 4 allocs, 4 frees, 64 bytes allocated
==22383==
==22383== All heap blocks were freed -- no leaks are possible
==22383==
==22383== For counts of detected and suppressed errors, rerun with: -v
==22383== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)


Always confirm that you have freed all memory you have allocated and that there are no memory errors.



Using last pointer with Forward-Chaining



Since you have a last pointer there is no need for a generic iteration of the list to find the last pointer. I suspect you are intending to use forward-chaining. In that case, you can simply modify append() as follows:



    if (!list->first)
list->first = node;
else
list->last->next = node;


(note: the list->last = node assignment is handled in the return)






share|improve this answer















While it is impossible to tell where your problem lies exactly, I suspect it lies in one of two places. One, you are initializing each data member with a string literal which is read-only on all but a very few systems. So if anywhere in your code you attempt to modify data you could expect a SegFault. The same would apply if you later attempt to free (pointer->data);



Two, you fail of assign your node->next pointers correctly leading to your traversal attempting to derefernce a NULL pointer or indeterminate pointer leading to the same SegFault. This can occur if your append function fails to handle the if (!list->first) { ... } case correctly or the else case where you will be required to set pointer->next = newnode;



There is really no way to tell unless you post a A Minimal, Complete, and Verifiable Example (MCVE), but given list operations are somewhat generic, you could correct the shortcomings with something similar to the following for your init() and append() functions (with an added print() and free() functions thrown in for good measure), e.g.



#include <stdio.h>
#include <stdlib.h>

struct list_elem {
struct list_elem *next; // Zeiger auf das naechste Element
char *data; // Zeiger auf ein Datenobject
};

typedef struct list {
struct list_elem *first;// erstes Element in der Liste
struct list_elem *last; // letztes Element in der Liste
} list_t;

/* function prototypes */
list_t *list_init ();
struct list_elem *list_append (list_t *list, char *data);
void list_print (list_t *list);
void list_free (list_t *list);

int main (void)
{
list_t *li = list_init();

if (list_append (li, (char){"erstes"}) == NULL ||
list_append (li, (char){"zweites"}) == NULL ||
list_append (li, (char){"drittes"}) == NULL) {
perror ("Cannot allocate memory" ) ;
exit (EXIT_FAILURE);
}

list_print (li);
list_free (li);

exit (EXIT_SUCCESS);
}

list_t *list_init (void)
{
list_t *newlist = malloc (sizeof *newlist);

if (!newlist) {
perror ("malloc-newlist");
exit (EXIT_FAILURE);
}

newlist->first = NULL;
newlist->last = NULL;

return newlist;
}

struct list_elem *list_append (list_t *list, char *data)
{
struct list_elem *node = NULL;

if (!list)
return NULL;

if (!(node = malloc (sizeof *node))) {
perror ("malloc-node");
return NULL;
}
node->data = data;
node->next = NULL;

if (!list->first)
list->first = node;
else {
struct list_elem *iter = list->first;
while (iter->next)
iter = iter->next;
iter->next = node;
}

return (list->last = node);
}

void list_print (list_t *list)
{
struct list_elem *iter = NULL;

if (!list)
return;

iter = list->first;

while (iter) {
printf ("%sn", iter->data);
iter = iter->next;
}
}

void list_free (list_t *list)
{
struct list_elem *iter = NULL;

if (!list)
return;

iter = list->first;

while (iter) {
struct list_elem *victim = iter;
iter = iter->next;
free (victim);
}

free (list);
}


Example Use/Output



$ ./bin/ll_list_elem
erstes
zweites
drittes


Memory Use/Error Check



There is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?



In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.



It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.



For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.



$ valgrind ./bin/ll_list_elem
==22383== Memcheck, a memory error detector
==22383== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==22383== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==22383== Command: ./bin/ll_list_elem
==22383==
erstes
zweites
drittes
==22383==
==22383== HEAP SUMMARY:
==22383== in use at exit: 0 bytes in 0 blocks
==22383== total heap usage: 4 allocs, 4 frees, 64 bytes allocated
==22383==
==22383== All heap blocks were freed -- no leaks are possible
==22383==
==22383== For counts of detected and suppressed errors, rerun with: -v
==22383== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)


Always confirm that you have freed all memory you have allocated and that there are no memory errors.



Using last pointer with Forward-Chaining



Since you have a last pointer there is no need for a generic iteration of the list to find the last pointer. I suspect you are intending to use forward-chaining. In that case, you can simply modify append() as follows:



    if (!list->first)
list->first = node;
else
list->last->next = node;


(note: the list->last = node assignment is handled in the return)







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 23 '18 at 7:13

























answered Nov 23 '18 at 6:56









David C. RankinDavid C. Rankin

41.8k32748




41.8k32748













  • I suspect you are correct -- added an example of forward-chaining with last.

    – David C. Rankin
    Nov 23 '18 at 7:13











  • Thank you for your answer. You have written: "You are initializing each data member with a string literal which is read-only on all but a very few systems.". -> How can I change that?

    – SQLLearner
    Nov 23 '18 at 7:34











  • Look how I used a "Compound Literal" to cast the string literals to (char ){...} making them an array of char (which you can change -- but not make longer). Note: the compound literal is only available C99+ or by specific compiler extension.

    – David C. Rankin
    Nov 23 '18 at 7:45



















  • I suspect you are correct -- added an example of forward-chaining with last.

    – David C. Rankin
    Nov 23 '18 at 7:13











  • Thank you for your answer. You have written: "You are initializing each data member with a string literal which is read-only on all but a very few systems.". -> How can I change that?

    – SQLLearner
    Nov 23 '18 at 7:34











  • Look how I used a "Compound Literal" to cast the string literals to (char ){...} making them an array of char (which you can change -- but not make longer). Note: the compound literal is only available C99+ or by specific compiler extension.

    – David C. Rankin
    Nov 23 '18 at 7:45

















I suspect you are correct -- added an example of forward-chaining with last.

– David C. Rankin
Nov 23 '18 at 7:13





I suspect you are correct -- added an example of forward-chaining with last.

– David C. Rankin
Nov 23 '18 at 7:13













Thank you for your answer. You have written: "You are initializing each data member with a string literal which is read-only on all but a very few systems.". -> How can I change that?

– SQLLearner
Nov 23 '18 at 7:34





Thank you for your answer. You have written: "You are initializing each data member with a string literal which is read-only on all but a very few systems.". -> How can I change that?

– SQLLearner
Nov 23 '18 at 7:34













Look how I used a "Compound Literal" to cast the string literals to (char ){...} making them an array of char (which you can change -- but not make longer). Note: the compound literal is only available C99+ or by specific compiler extension.

– David C. Rankin
Nov 23 '18 at 7:45





Look how I used a "Compound Literal" to cast the string literals to (char ){...} making them an array of char (which you can change -- but not make longer). Note: the compound literal is only available C99+ or by specific compiler extension.

– David C. Rankin
Nov 23 '18 at 7:45













0














i think you are not allocate memory in proper way.



TList *list_init()
{
TList *newList = (TList *) malloc(sizeof(TList));

newList->first = (struct list_elem *) malloc(sizeof(structlist_elem));
newList->last = (struct list_elem *) malloc(sizeof(struct list_elem));

newList->first->next= NULL;
newList->last->next= NULL;

return newList;
}





share|improve this answer
























  • This code is weird, there are typos, the types are not the same as in the question and it doesn't answer the question at all.

    – Jabberwocky
    Nov 23 '18 at 7:05








  • 1





    Allocating for first and last in init() will greatly complicate your append() function. (not to mention updating last)

    – David C. Rankin
    Nov 23 '18 at 7:05













  • @Jabberwocky , because we don't have enough information of list append.

    – raka
    Nov 23 '18 at 7:10
















0














i think you are not allocate memory in proper way.



TList *list_init()
{
TList *newList = (TList *) malloc(sizeof(TList));

newList->first = (struct list_elem *) malloc(sizeof(structlist_elem));
newList->last = (struct list_elem *) malloc(sizeof(struct list_elem));

newList->first->next= NULL;
newList->last->next= NULL;

return newList;
}





share|improve this answer
























  • This code is weird, there are typos, the types are not the same as in the question and it doesn't answer the question at all.

    – Jabberwocky
    Nov 23 '18 at 7:05








  • 1





    Allocating for first and last in init() will greatly complicate your append() function. (not to mention updating last)

    – David C. Rankin
    Nov 23 '18 at 7:05













  • @Jabberwocky , because we don't have enough information of list append.

    – raka
    Nov 23 '18 at 7:10














0












0








0







i think you are not allocate memory in proper way.



TList *list_init()
{
TList *newList = (TList *) malloc(sizeof(TList));

newList->first = (struct list_elem *) malloc(sizeof(structlist_elem));
newList->last = (struct list_elem *) malloc(sizeof(struct list_elem));

newList->first->next= NULL;
newList->last->next= NULL;

return newList;
}





share|improve this answer













i think you are not allocate memory in proper way.



TList *list_init()
{
TList *newList = (TList *) malloc(sizeof(TList));

newList->first = (struct list_elem *) malloc(sizeof(structlist_elem));
newList->last = (struct list_elem *) malloc(sizeof(struct list_elem));

newList->first->next= NULL;
newList->last->next= NULL;

return newList;
}






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 23 '18 at 7:02









rakaraka

11




11













  • This code is weird, there are typos, the types are not the same as in the question and it doesn't answer the question at all.

    – Jabberwocky
    Nov 23 '18 at 7:05








  • 1





    Allocating for first and last in init() will greatly complicate your append() function. (not to mention updating last)

    – David C. Rankin
    Nov 23 '18 at 7:05













  • @Jabberwocky , because we don't have enough information of list append.

    – raka
    Nov 23 '18 at 7:10



















  • This code is weird, there are typos, the types are not the same as in the question and it doesn't answer the question at all.

    – Jabberwocky
    Nov 23 '18 at 7:05








  • 1





    Allocating for first and last in init() will greatly complicate your append() function. (not to mention updating last)

    – David C. Rankin
    Nov 23 '18 at 7:05













  • @Jabberwocky , because we don't have enough information of list append.

    – raka
    Nov 23 '18 at 7:10

















This code is weird, there are typos, the types are not the same as in the question and it doesn't answer the question at all.

– Jabberwocky
Nov 23 '18 at 7:05







This code is weird, there are typos, the types are not the same as in the question and it doesn't answer the question at all.

– Jabberwocky
Nov 23 '18 at 7:05






1




1





Allocating for first and last in init() will greatly complicate your append() function. (not to mention updating last)

– David C. Rankin
Nov 23 '18 at 7:05







Allocating for first and last in init() will greatly complicate your append() function. (not to mention updating last)

– David C. Rankin
Nov 23 '18 at 7:05















@Jabberwocky , because we don't have enough information of list append.

– raka
Nov 23 '18 at 7:10





@Jabberwocky , because we don't have enough information of list append.

– raka
Nov 23 '18 at 7:10


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53440775%2fsegmentation-fault-list-initializing%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Costa Masnaga

Fotorealismo

Sidney Franklin