|
This value looks fine, so to find out what is occurring, you will need to step into the open command and see how the failure occurs:
--------------------------------------------------------------------------------------------------------
(gdb) step
Cannot insert breakpoint 0:
Temporarily disabling shared library breakpoints:
0
Program received signal SIGSEGV, Segmentation fault.
0x40000031 in ?? () from /lib/ld-linux.so.2
--------------------------------------------------------------------------------------------------------
Well, not much luck there; the failure occurs in a shared library and gdb can’t let us know what is going on in there as things stand right now. We are able to link the symbol table from a shared object in with gdb, but there will be no debugging symbols, and we will simply have to step through each function manually. This library could be recompiled with debugging symbols and linked directly, but that would take a large amount of time and effort; so maybe it is possible to
take the data we’ve gotten from the debugger so far and think about what it tells us might be happening.
It certainly appears that the value of ttydata is correct, so it is very odd that it would be causing a segmentation fault. Segmentation faults rarely have anything to do with what the actual data in a memory address is though; they have more to do with overwriting or deleting memory that is already assigned to another object in a program. Given that ttydata has just been written to by a
sprintf command, and that ttydata is the variable we are passing into the open command that fails, it seems possible that there is an issue with the address space it is using to store its value in. So, to look at what is going on with the space for tty before it is written to by sprintf, run the program again in the debugger, with the same break point at line 44 and print out ttydata prior to
its being assigned:
--------------------------------------------------------------------------------------------------------
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/support/nthomas/src/hello/a.out
Breakpoint 1, massivehello (message=0x804881f "Hello World!\n") at hw2.c:44
44 sprintf(ttydata, "/dev/%s", utmp->ut_line);
(gdb) print ttydata
$2 = 0x8049850 "\234\230\004\bh3\001@‘\236"
------------------------------------------------------------------------------------------------------
That memory region looks like maybe it is being used by something else. We can use the ’x’
command to look at what it is that the is at the address where this points - (0x8049850):
--------------------------------------------------------------------------------------------------------
(gdb) x 0x8049850
0x8049850 <_GLOBAL_OFFSET_TABLE_>: 0x0804989c
(gdb) x 0x0804989c
0x804989c <_DYNAMIC>: 0x00000001
--------------------------------------------------------------------------------------------------------
That certainly doesn’t look like an empty character string, like we’d expect. It looks likely at this point that ttydata is using someone else’s address space to try and store its data. Why could that be? Well, looking back at the source code, it may be obvious by now that the mistake in the coding was that the char pointer ’ttydata’ was never initialized or assigned memory, so when data is written to it that data may well write over previously assigned memory. Because of the
transient nature of these sorts of memory failures, as previously mentioned, you may not have experienced the failure in the same location, or even at all. However, this sort of memory-related bug is fairly common, and often requires the use of gdb to resolve. Had gdb not pointed us towards where the failure actually occurred in the code, it might have taken significantly longer to locate the mistake.
So, to rectify this we need to allocate space for ttydata, which stores a device name; most of the devices that are available under Linux have names that are 7 characters or less, but to be on the safe side (since this is only a single variable, and therefore doesn’t account for much space), a size of 50 characters will be fine. So, add the following lines to the program above to allocate
space and then free it for ttydata (the mistakes are not coded into the versions of the program shown at the end of this text- see the next section for more on this):
At line 25 (just under the variable declarations in massivehello()):
-------------------------------------------------------------------------------------------------------
ttydata = (char*)malloc(50*sizeof(char));
------------------------------------------------------------------------------------------------------
At line 65 (just before the return() in massivehello()):
-----------------------------------------------------------------------------------------------------
free(ttydata);
----------------------------------------------------------------------------------------------------
自己弄这方面比较少,有些东西不是很清楚.请高手帮忙!!!!! |
|