Print the value of a local variable through GDB - debugging

while debugging I need to print the value of a variable that is declared in the else block. something like this :
if(condition){
}
else {
string str = "abcd";
strcpy(globalvariable,str,sizeOf(str));
}
I want to see the value of str.

Run the program inside the debugger.
Set break point to stop the execution of program sequence using break command. In your case, (gdb) break strcpy to break every time it is being called strcpy in else.
To print you can use any of the following, x str, x/s str, print str, print "%s", str.

You can't see the value of str if condition is true during program flow because it does not exist in memory in this case.
You have to enter else block somehow, either during normal program flow or using gdb jump command.

Related

How can I detect breakpoints in GDB command files and stop the execution?

I am trying to implement a single stepping using GDB command file. I would like to stop executing the command file whenever I encounter any breakpoint.
Is there a way to detect that a breakpoint was hit? and also how can I stop executing the command file after that.
I checked the documantation and it seems like I only can have break commands for certain breakpoints. But not for a random breakpoint.
I have something like this:
printf "single stepping\n"
set $steps_count = 0
while ($steps_count < 5)
set $steps_count = $steps_count + 1
printf "program counter 0x%x\n", $pc
printf "next #%d\n", $steps_count
next
end
And this is what I want to achieve:
printf "single stepping\n"
set $steps_count = 0
while (# breakpoint is not hit)
set $steps_count = $steps_count + 1
printf "program counter 0x%x\n", $pc
printf "next #%d\n", $steps_count
next
end
# end the execution of the command file.
update:
I tried to use the follwing:
# set the end breakpoint
break *0x199e
commands
stop 1
quit
end
break *0x1980
# set a certain once we encounter the first breakpoint
commands
set $count = 0
while $count < 5
printf "#PC: 0x%x", $pc
set $count = $count + 1
stepi
end
end
This should start logging the program counter once the first breakpoint is hit. But I don't know why this break command doesn't work. Once the breakpoint is hit the program stops and the while loop is not entered!
Update:
according to the gdb documentation:
Any other commands in the command list, after a command that resumes execution, are ignored. This is because any time you resume execution (even with a simple next or step), you may encounter another breakpoint--which could have its own command list, leading to ambiguities about which list to execute.
so I don't think it is a good idea to put a loop that has step or next in break commands.
Try something like:
commands 1-10 # for breakpoints number 1 through 10
set $breakpoint_hit = 1
end
Then check for that in your loop.

Why does an error occur when I try to test if a member variable (string) in a class is empty?

I'm working on a project and need to test one of my class' member variables to verify that the user did indeed enter a string.
I've also tried using (patronName == '') and (patronName == "") but have had no luck.
Edit: Using "\n" fixes the error but the program ends without allowing the user to enter a name.
std::string Restaurant::getPatronName()
{
bool controlFlag = true;
do
{
getline(std::cin,patronName);
if ((std::cin.fail()) || (patronName == '\n'))
{
std::cout << "You must enter a name!" << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
else
{
controlFlag = false;
}
} while (controlFlag);
return patronName;
}
The function should read and store the name entered by the user into patronName. When trying to build, I get an error that says "no match for 'operator=='". Could this be because the object called in main is a pointer of type Restaurant?
Besides the type mismatch between the character '\n' and the std::string patronName, we can find at https://en.cppreference.com/w/cpp/string/basic_string/getline that std::getline(input, str, delim);
Extracts characters from input and appends them to str until […] the next available input character is delim, […], in which case the delimiter character is extracted from input, but is not appended to str.
So there won't be any '\n' character, if delim is the newline, in the first place.
You can use std::basic_string::empty() to check if a string is empty.
What happens with '\n' is you are comparing a string with a char, which, i suspect, there is no operator== defined for this case. If you are sure the string isn't empty, you can call operator[] formerName[0], which returns a char.
You have to write patronName == "\n" because you cannot compare string and character

Why does the debugger have to jump "back and forth" before it sets my tuple value?

I've actually fixed this problem already (while documenting it for this post), but I still want to know is why it is happening, so that I can understand what I did and hopefully avoid wasting time with it in the future.
In a Swift project, I have a function that parses out a string that I know will be presented in a specific format and uses it to fill in some instance variables.
There is a helper function that is passed the string, a starting index, and a divider character and spits out a tuple made up of the next string and the index from which to continue. Just in case a poorly formatted string gets passed in, I define a return type of (String, Int)? and return nil if the divider character isn't found.
The helper function looks, in relevant part, like this:
func nextChunk(stringArray: Array<Character>, startIndex: Int, divider: Character) -> (String, Int)?
{
[...]
var returnValue: (String, Int)? = (returnString, i)
return returnValue
}
So far, so good. I set a breakpoint, and just before the function returns, I see that all is as it should be:
(lldb) po returnValue
(0 = "21三體綜合症", 1 = 7)
{
0 = "21三體綜合症"
1 = 7
}
That's what I expected to see: the correct string value, and the correct index.
However, when I go back to the init() function that called the helper in the first place, and put a breakpoint immediately after the call:
var returnedValue = self.nextChunk(stringArray, startIndex: stringArrayIndex, divider: " ")
I get a completely different value for returnedValue than I had for returnValue:
(lldb) po returnedValue
(0 = "I", 1 = 48)
{
0 = "I"
1 = 48
}
Now here's the really weird part. After I get the return value, I want to test to see if it's nil, and if it's not, I want to use the values I fetched to set a couple of instance variables:
if(returnedValue == nil)
{
return
}
else
{
self.traditionalCharacter = returnedValue!.0
stringArrayIndex = returnedValue!.1
}
If I comment out both of the lines in the "else" brackets:
else
{
// self.traditionalCharacter = returnedValue!.0
// stringArrayIndex = returnedValue!.1
}
then my original breakpoint gives the expected value for the returned tuple:
(lldb) po returnedValue
(0 = "21三體綜合症", 1 = 7)
{
0 = "21三體綜合症"
1 = 7
}
Again: the breakpoint is set before this if/else statement, so I'm taking the value before any of this code has had the chance to execute.
After banging my head against this for a few hours, I realize that...there isn't actually a problem. If I press the "step over" button in the debugger, the execution pointer jumps back from the if() line to the call to nextChunk. Pressing it again sends it forward to "if" again, and sets the values properly.
This extra double-jump only happens if the assignment code is active, consistently and reproducibly. As I know, since I reproduced it for hours trying to figure out what was wrong before even trying stepping forward and noticing that it "fixed itself."
So my question is: why? Is this a bug in the debugger, or am I using breakpoints wrong? It happens just the same whether I put the breakpoint between the function call and the if() or on the if() line. Can someone explain why the debugger is jumping back and forth and when the value I need is actually getting set?

Difficulties understanding the mechanism of retrieving parameter values passed to a script in a function

The script passes two parameter values to another instance of the script. So the built-in parameter variable, 0, contains the number of passed parameters. 1 is in the below example "C:/Windows" and 2 is "/switchtest"
It is possible to assign the parameter values to strParam1 and strParam2 with the traditional method outside the function (with the single equal sign). However, inside a function, the assignments fail.
If they are assigned in a loop with the := sign, it seems to work.
Why is it? Can anybody explain this behavior?
strParam1 = %1%
strParam2 = %2%
msgbox, 64, Outside the Function, number of parameters:%0%`npath: %strParam1%`nswitch: %strParam2%
test_params()
strPath := "C:/Windows"
strSwitch := "/switchtest"
RunWait "%A_AhkPath%" "%A_ScriptFullPath%" "%strPath%" "%strSwitch%"
test_params() {
global 0
; this works
; loop %0%
; strParam%A_Index% := %A_Index%
; this causes an error: "This dynamic variable is blank. If this variable was not intended to be dynamic, remove the % symbols from it."
; strParam1 := %1%
; strParam2 := %2%
; this passes empty values; however, this method works outside the function.
strParam1 = %1%
strParam2 = %2%
msgbox, 64, Inside the Function, number of parameters:%0%`npath: %strParam1%`nswitch: %strParam2%
if strParam2
exitapp
}
You had the right idea with global 0; that allows %0% to carry into the function from toplevel. You just need to declare global 1, 2 as well.
Even if you do this, you can't use := to assign them to variables, because := deals with expressions and there is no syntax to use them in expressions (normally a variable is referred to in an expression with the variable name alone, without %%; obviously 1 and 2 are interpreted as actual numbers instead of variables).
#echristopherson answered the question, but I'd like to propose a workaround. This assumes you're using AutoHotkey_L.
If you run the test script with the args "a b c", it gives you this.
3
1, a
2, b
3, c
The test:
argv := args()
test := argv.MaxIndex() "`n"
for index,param in argv
test .= index ", " param "`n"
MsgBox % test
And the function:
args() {
global
local _tmp, _out
_out := []
Loop %0% {
_tmp := %A_Index%
if _tmp
_out.Insert(_tmp)
}
return _out
}

GDB If statement return values?

Is there a way I can read if statements being evaluated? I mean, like get the return value of realpath in -
if(realpath(path.c_str(), realPath) == 0)
You can step into and finish realpath function. The returned value will be printed on screen.
at the gdb prompt (if you got debug symbols enabled when you compiled)
print realpath(path.c_str(),realPath)
it will print the result, very nifty.
If you had a memory pointer laying around on your code, you could use GDB to allocate new memory space for it it, and use it to store the result of the expression you want to evaluate.
Check this page for more info.
(gdb) set variable p = malloc(sizeof(int))
(gdb) print p
$2 = (int *) 0x40013f98 (address allocated by malloc)
(gdb) set variable *p = 255
(gdb) print *p
$3 = 255

Resources