deejaybags <> wrote:
>could someone please have a look at this and tell me why it segfaults. i
>am confused as all hell!
>
>stringman.h
>void load_string(char *newString);
>char * remove_string();
>char * remove_upper_string();
>char * remove_lower_string();
>
>(i havent written the removes yet);
>
>then the source
>stringman.c
>#include <stdio.h>
>#include <stdlib.h>
>#include <string.h>
>/* fundamental structure definition */
>typedef struct list_member{
> char *m_data;
> struct list_member *m_next;
>} MEMBER;
>
>// initalise head pointer
>MEMBER *headptr;
>
>void load_string(char *newString)
>{
> printf("checkpoint1");
> //create new list_member for new string
> MEMBER *newmem, *curr;
> printf("checkpoint2");
> if((newmem=(MEMBER *)malloc(sizeof(MEMBER)))==(MEMBER *)0)
Better:
if ( ( newmem = malloc( sizeof *newmem ) ) == NULL )
But that's not the problem.
> {
> printf("checkpoint2a");
> fprintf(stderr, "out of memory in new_member\n");
> }
> else
> {
> printf("checkpoint2b");
> /* create memory to copy data into*/
> newmem->m_data = (char *)malloc(strlen(newString)+1);
Better:
newmem->m_data = malloc( strlen( newString ) + 1 );
You failed to check malloc()s return value.
But that's not the problem.
> printf("checkpoint2c");
> /* copy data into structure, assuming it is a string */
> strcpy(newmem->m_data, newString);
> printf("checkpoint2d");
> /* set the pointer in the structure to null */
> newmem->m_next = (MEMBER *)0;
Better:
newmem->m_next = NULL;
But that's still not the problem.
> }
> printf("checkpoint3");
> // set current to 1st list_member
> curr = headptr;
Caaaaarefully...
> printf("checkpoint4");
> // check if list is empty
> if(curr->m_next == (MEMBER *)0)
Gotcha!!!
You failed to allocate some memory for headptr (and therefore curr)
to point to, so curr->m_next invokes dreaded undefined behaviour.
> {
> printf("checkpoint4a");
> headptr->m_next = newmem;
> }
Change the above to:
// check if list is empty
if( headptr == NULL )
{
printf("checkpoint4a");
headptr = newmem;
}
> else
> {
> // go to the end of the list
> printf("checkpoint4b");
> while(curr->m_next != (MEMBER *)0)
> {
> printf("checkpoint4c");
> curr = curr->m_next;
> }
That's a very inefficient way to do it. Maybe you want to maintain a
pointer to your last element, or just insert at the head of the list.
> printf("checkpoint5");
> // change last ptr to point to current
> curr->m_next = newmem;
> printf("checkpoint6");
> }
>}
>
>
>then the testing program
>test.c
>#include "stringman.h"
>
>int main()
>{
> char *test = "test1", *test2= "test2", *test3 =
>"123456789101112131415161718192021222324252627282 930313233343536373839404
>1424344454647484950515253545556575859606162636465 666768697071727374757677
>7879808182838485868788899091929394959697989910010 110210310410510610710810
>9110111112113114115116117";
> printf("\n test = %s\n",test);
> printf("\n test2 = %s\n",test2);
> printf("\n test3 = %s\n",test3);
> load_string(test);
> printf("load1ok");
> load_string(test2);
> printf("load2ok");
> load_string(test3);
> printf("load3ok");
> printf("all loaded ok so it looks like");
>}
>
>
>and then the output
>
>
>$ ./test
>
> test = test1
>
> test2 = test2
>
> test3 =
>1234567891011121314151617181920212223242526272829 3031323334353637383940
>4142434445464748495051525354555657585960616263646 566676869707172737475767
>7787980
>8182838485868788899091929394959697989910010110210 310410510610710810911011
>1112113
>114115116117
>Segmentation fault (core dumped)
>
>as you can see, it seams to dump before any of the code in load_string()
>is run.
Right, it /seems/ so, but: if you just had appended a '\n' to the
strings you print at your checkpoints (or did a fflush(stderr) after
each printf), you would have noticed that your program runs fine till
"checkpoint4" is printed, and then segfaults - reason given above.
>im ****ing confused as hell. like how can it dump before printing
>checkpoint 1, its the 1st thing in string_load() so how is it dumping
>before that...
Relax, we've all gone through it.
Some more suggestions:
- don't use C99 single line comments when posting code here: it may
result in broken code if a line is wrapped by the newsreader, and
some people use compilers not capable to deal with //-comments
- do not cast the return value of malloc: you gain nothing but hiding
the fact you eventually forgot to #include <stdlib.h>
- just use NULL insted of (some_type *)0, that's what it is made for
- it's better style to write
my_ptr = malloc( sizeof *my_ptr * NUMBER );
instead of
my_ptr = malloc( sizeof (my_ptr_type) *NUMBER );
If the type of my_ptr ever changes in the future, you do not have to
go through your code and fix all the malloc()s.
Regards
Irrwahn
--
I can't see it from here, but it looks good to me.