![]() |
|
#1
|
||||
|
||||
need 'pointers' on deaing with segmentation faultsHello there guys.
I have been reading various interesting posts on this forum about segmentation faults and I wish to now use the things learnt to debug my very own piece of code. If u remember I had a post named 'Help Analyzing a Linked List' sometime back which got pretty bloated. Nevertheless I could finally implement my simple singly-Linked Linked list and the final (kind of) working code is repeated below. CPP / C++ / C Code:
And the file list.c is here: CPP / C++ / C Code:
Code:
To describe a typical testing sequence, I go on adding elements using the option 1 and in any order..ive tried inserting elements between two elements and ive tried adding elements to the tail and to the head and it seems to be working. The problem seems to be that when i access the displaylist function for the second time, after inserting an element in the list, I get the bus error. Moreover, I think that the display list function is using some other variable (not the actual associated with list) to display the elements. This is because even after choosing option 2 for destroying the list, option 4 is still able to display the elements. On using (my relatively amateurish skills with)gdb to track whats going on..i came across certain findings. when i tried adding a new element which falls somewhere between the head and the tail of the list, the variable mydata got allocated a memory location which was the present tail of the list, i.e. mydata was equal to list->tail even after the statement containing the malloc function was executed in testlist.c. This obviously meant that we have two variables trying to access the same memory location and I suspected a segmentation fault and it very naturally gave the bus error. Well..what i do not get is why is malloc assigning such a location to mydata when it knows that list->tail already has possession over that piece of memory? Furthermore as described earlier, when i tried to destroy the list before ever opting to print the contents, it was still able to print the contents of the list after executing the complete deallocatelist function. On using gdb again, it showed that the local head variable inside deallocatelist was being changed on every iteration of the while loop, but the head variable of the list (list->head that is) remained completely unchanged and so was the tail. Any clues?? Hope to hear from you guys, __________________
Hope to hear from you guys! -------------------------------------------------- Best Regards, Aijaz Baig. |
||||
|
#2
|
|||
|
|||
Re: need 'pointers' on deaing with segmentation faultsQuote:
Once you notice things like this (courtesy of gdb or whatever), the idea is to figure out how that could happen. Look at your list_ins_next code: CPP / C++ / C Code:
Consider something like the following: CPP / C++ / C Code:
If this is an example from an elementary book, I think that it's not very well suited for inexperienced programmers. All of the casting from void pointers to pointers to int (and vice-versa) that are there supposedly to make the algorithms generic in nature really get in the way of understanding the fundamentals of manipulating linked list structures. Things like copying a pointer value rather than copying the data value that you get from the dereferenced pointer could happen to anyone, but to people without a lot of experience, it may be pretty hard to see, especially with the visual clutter of all of the casts that are required by these struct definitions. And the bottom line is that it only works for ints anyhow. Any changes to make the list work for other data types will involve massive error-prone manual editing of every single one of the routines anyhow. (But that's only an opinion, and I know that different people have different ways of teaching and different ways of learning. Things that work for some people might not be very good for others. I also know that not everyone agrees with my opinion(s), and that's OK. Really.) Regards, Dave |
|
#3
|
||||
|
||||
Re: need 'pointers' on deaing with segmentation faultsHi there Dave.
Quote:
Hmm..so u mean I should create a new variable dynamically within the list_ins_nxt function such that it should be able to 'hold' the data value that would be inserted into the list, right? So rather than allocating a memory location for the variable new_elmt I should allocate storage for the int. pointer that is passed in the form of the variable data. Fine. I can see that from the modified code. However what does this statement stand for: CPP / C++ / C Code:
Does it mean that 'if whatever new_element points to is a NULL....' ? And in the first if statement you directly compare the variable 'new_element' to NULL. I suppose since it is an auto variable, it will get created automatically on arrival at the function isn't it?..so we do not need to use malloc to create it.. Now that is a pretty handy tip you showed there!.. Well..I will try incorporating these changes in my program and see what ensues. By the way, do u have anything to comment on the deallocatelist function and the way I have tried to use it to destroy the list? It does not seem to do anything to the actual list variables outside the function. And the thought of having the self-destructive destroy function a part of the list itself seems to be pretty bizarre to me. Is it normal practice amongst pros to do such a thing? Waiting eagerly for your replies, __________________
Hope to hear from you guys! -------------------------------------------------- Best Regards, Aijaz Baig. |
|
#4
|
||||
|
||||
Re: need 'pointers' on deaing with segmentation faultsQuote:
CPP / C++ / C Code:
CPP / C++ / C Code:
Quote:
CPP / C++ / C Code:
Quote:
Quote:
Now, you shouldn't free things until you are through with them. Here is a bug that could create some of your problems CPP / C++ / C Code:
On the other hand in your "remove" function you don't free the memory allocated to the node that you are removing. That's a memory leak. It wouldn't cause this small program to crash or anything, and fixing it won't make this little program perform better, but it is a bug that should be fixed. Note that when the program is terminated, the operating system reclaims memory and other resources that have been given to that process, but as long as a process is active, if it gets more and more resources without ever giving it back to the system, that's a problem. I think it's a good habit to getinto: deallocate dynamic memory objects when you are through with them, even though it might not be strictly necessary at the end of the program. Regards, Dave |
|
#5
|
||||
|
||||
Re: need 'pointers' on deaing with segmentation faultsHi.
Quote:
Nevertheless, about the variable new_element, the program seems to be correctly displaying the elements in the list if I ignore the malloc statement and the free statement. So as u said, new_element need not be freed as it is pointing at the variable of the type listelmt and doing so causes the bus error i'd think. Hence I have removed the free statement and also the malloc statement. Now, moving over to the function deallocatelist, i will post the output of the gdb debugger to show how things look when i try to use the function to destroy the list. I make heavy use of the bt full and the print gdb commands which are used to show the contents of the stack alongwith all the local variables for the former and printing the value of the variable in question for the latter. I set up a breakpoint at line 34 in list.c and when the execution reaches that place, i step thru the program and check the variables as i mentioned above. By the way, I have renamed some variables to make it easy to understand if its a pointer or a piece of data. 'mydata' is now 'crrnt_data_ptr' and rmvd_data is now 'rmvd_data_handle'. Nevertheless, the variables inside the deallocatelist function have been left unchanged. heres what i see as i enter deallocatelist function: Code:
Code:
Code:
hence the 'head' variable is merely toggled between the values of the listelmt address without those memory locations being actually freed from the program memory. hence even after the whole cycle of 'seemingly' freeing the memory, on checking option 4, i am able to see all the elements of the list perfectly intact. I guess I am missing something fundamental here. Eager to hear from you guys. __________________
Hope to hear from you guys! -------------------------------------------------- Best Regards, Aijaz Baig. |
|
#6
|
|||||
|
|||||
Re: need 'pointers' on deaing with segmentation faultsQuote:
Quote:
Quote:
I don't have any idea what you are talking about. I don't see anywhere that you have used free(new_element) in the code that you have posted. Please note: If you execute free(anypointer) it deallocates the memory that is pointed to by anypointer, and your program can not legally access that memory after that point. The variable anypointer itself is still there. You can't legally dereference it. You can't legally call free() with that variable again. It can be used again (that is: it can be assigned another value with another malloc() or whatever). If you use free() to de-allocate some dynamic memory and the program subsequently tries to access that memory, the behavior is undefined. It may "just happen" that it seems to work for some test conditions if nothing in the system has caused that block of memory to be allocated somewhere else. Undefined behavior means undefined. It is not guaranteed that violating some of the rules will always cause an error to manifest itself. It is still a program bug if you do it, and if getting the "right answer" makes you believe that it is not a bug, then that's too bad. Undefined means undefined. There is absolutely nothing to be gained by trying to guess whether a given bug like this will always cause some particular behavior. Quote:
For beginning programmers I suggest that they use print statements so that I can run their program on my system and display exactly what they are seeing. I have never been successful in following someone else's steps when they "tell me" what they did. Period. Debuggers are powerful tools and even beginners can learn to use them effectively. It's just that I don't have the time or patience to try to step through things unless I am physically present and looking over their shoulder when they try to make it work. One more time: Undefined behavior is undefined. Looking at unallocated memory with a debugger or with a print statement is absolutely unproductive. Why bother? Quote:
Yes. You are wasting your time looking at memory blocks that have been deallocated (and therefore can not be legallly used by your program). SInce they can not be legally used by your program, why would you waste so much effort on trying to understand more about their contents? Regards, Dave |
|
#7
|
||||
|
||||
Re: need 'pointers' on deaing with segmentation faultsQuote:
In keeping with your suggestion to use printfs for you to track whats happening, I have made some small modifications to my original. However I have changed the variable names in a lot of different places and hence I show all the three source files again, (hoping it wont irritate people here Heres the source code: testlist.c: CPP / C++ / C Code:
list.h: CPP / C++ / C Code:
list.c: CPP / C++ / C Code:
And it is this following piece of output that I am concerned about: Code:
Could you also explain why we need the following in case of the list.h file: CPP / C++ / C Code:
CPP / C++ / C Code:
Hope to hear from you, __________________
Hope to hear from you guys! -------------------------------------------------- Best Regards, Aijaz Baig. |
|
#8
|
|||
|
|||
Re: need 'pointers' on deaing with segmentation faultsQuote:
I chose my words very carefully. What I said was: Quote:
Note the word legally. Note the word undefined. How many times did I use the word legally? I don't mean that if you do something "illegal" in your C program that the C Police will knock down your door, put you in handcuffs, and carry you off to jail. I mean that if you do something that is "illegal" and it leads to undefined behavior then your program has a bug. Even though the bug may not manifest itself in your test case, it is a bug. I also said Quote:
If you want to print out values of the contents of memory that has been deallocated just to see what happens, you are perfectly free to do so (without fear of imprisonment), but I am really (really) not interested. I really don't see any point, at this stage of the game, in investigating what happens when a program deliberately indulges in undefined behavior. You have already established that sometimes the memory still contains what had been previously stored there. So what? The behavior is still undefined. The program is not guaranteed to crash, but it might. The system is not guaranteed to save old values in memory after it is deallocated, but it might. The C language allows you to do many things with invalid code with results that sometimes give something that you did or did not expect. Sigh. End of transmission. Over and out. -30- Regards, Dave Last edited by davekw7x : 17-Aug-2007 at 10:11.
|
Recent GIDBlog
Vista ?Widgets? on Windows XP by LocalTech
| Thread Tools | Search this Thread |
| Rate This Thread | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Sort an array of structures | sassy99 | C Programming Language | 10 | 15-Feb-2007 08:46 |
| Pointer Usage in C++: Beginner to Advanced | varunhome | C++ Forum | 0 | 19-Aug-2005 10:25 |
| [Tutorial] Pointers in C (Part II) | Stack Overflow | C Programming Language | 0 | 27-Apr-2005 18:36 |
| [Tutorial] Pointers in C (Part I) | Stack Overflow | C Programming Language | 1 | 08-Apr-2005 19:35 |
Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The