GDB print whole pointers tree - gdb

Let a laziest linked list like:
#include <assert.h>
[...]
struct value {
int i_;
};
struct values {
struct value * first;
struct values * next;
};
[...]
struct values values_;
[...]
assert(values_ != NULL);
assert(values_->first != NULL);
assert(values_->first->i_ == 4);
assert(values_->next != NULL);
assert(values_->next->first != NULL);
assert(values_->next->first->i_ == 8);
assert(values_->next->next == NULL);
I read in https://stackoverflow.com/a/46289993 that print *values_ is an improvement over print values_, then print values_->first and print values_->next.
But I don't know how to end up with something like $i = {first = 0x?????? {i_ = 4}, next = 0x?????? {first = 0x?????? {i_ = 8}, next = 0x0}} using a single gdb command.
There is https://stackoverflow.com/a/16493871/1737973 and https://sourceware.org/gdb/current/onlinedocs/gdb/Pretty-Printing.html. Is there any laziest way than those?

You could do something lie this (untested):
(gdb) define plist
set var $h = $0
while $h != 0
print *$h
set var $h = $h->next
end
end
and then use (gdb) plist values_.

Related

If else not working in android inside for and while loop

public void LoadRoutine() {
TableRow tbrow0 = new TableRow(getActivity());
//String[] mStrings = new String[9];
tbrow0.setBackgroundColor(Color.parseColor("#FFFFFF"));
tbrow0.setLayoutParams(new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
for (String c : TimeSlotSummer) {
TextView tv0 = new TextView(getActivity());
tv0.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT));
tv0.setGravity(Gravity.CENTER);
tv0.setTextSize(12);
tv0.setHeight(40);
tv0.setWidth(76);
tv0.setBackgroundColor(Color.parseColor("#FFFFFF"));
tv0.setTextColor(Color.parseColor("#000000"));
tv0.setPadding(1, 1, 1, 1);
tv0.setText(c);
tv0.setBackgroundColor(R.id.tableRowid);
tbrow0.addView(tv0);
}
tableLayout.addView(tbrow0);
String dept = GlobalClass.userDepartment;
DatabaseAccess databaseAccess = DatabaseAccess.getInstance(getActivity());
databaseAccess.Open();
String faccode = GlobalClass.faculty_code;
Cursor cRoutine = databaseAccess.getRoutine("Sunday",dept);
if (cRoutine.getCount() == 0) {
Toast.makeText(getActivity(),"No Data in Table",Toast.LENGTH_LONG).show();
}
else{
while (cRoutine.moveToNext())
{
String[] mStrings = new String[10];
mStrings[0] = cRoutine.getString(2);
mStrings[1] = cRoutine.getString(4);
mStrings[2] = cRoutine.getString(5);
mStrings[3] = cRoutine.getString(6);
mStrings[4] = cRoutine.getString(7);
mStrings[5] = cRoutine.getString(8);
mStrings[6] = cRoutine.getString(9);
mStrings[7] = cRoutine.getString(10);
mStrings[8] = cRoutine.getString(11);
TableRow tbrow1 = new TableRow(getActivity());
tbrow1.setBackgroundColor(Color.parseColor("#FFFFFF"));
tbrow1.setLayoutParams(new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
for (String cls:mStrings) {
TextView tv1 = new TextView(getActivity());
tv1.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT));
tv1.setGravity(Gravity.CENTER);
tv1.setTextSize(12);
tv1.setWidth(75);
tv1.setHeight(37);
tv1.setBackgroundColor(Color.parseColor("#FFFFFF"));
tv1.setPadding(1, 1, 1, 1);
tv1.setBackgroundColor(R.id.tableRowid);
tv1.setText(cls);
tv1.setTextColor(Color.parseColor("#FF0000"));
if(cls.contains(faccode))
tv1.setTextColor(Color.parseColor("#000000"));
else
tv1.setTextColor(Color.parseColor("#FF0000"));
tbrow1.addView(tv1);
}
tableLayout.addView(tbrow1);
}
}
}
Inside the last for loop, without if-else, it works properly, but with if-else it is not working, that is apps shut down and mobile restart again.
Any one help me, I want to check some substring, then text color will change, otherwise color normal.
It would help if you posted a stack trace but if the crash occurs here:
if(cls.contains(faccode))
tv1.setTextColor(Color.parseColor("#000000"));
else
tv1.setTextColor(Color.parseColor("#FF0000"));
The only explanation is that you get a NullPointerException on cls because tv1 is obviously not null if it did not crash before.
Use this code instead:
if(cls != null && cls.contains(faccode))
tv1.setTextColor(Color.parseColor("#000000"));
else
tv1.setTextColor(Color.parseColor("#FF0000"));

Why can't I assign an int to the union member of a struct member?

I'm trying to assign a value to the member of an union which is member of a struct, but the value doesn't seem to be assigned.
I've stepped through the program, and right after the assignation, len_param.data value seems to be some sort of pointer (see GDB output at the end of the post)
Also, if I printf, it runs normally:
len_param.data.v_int = 4;
// If I uncomment this line, IT RUNS FINE! WHY?
// printf("len_param.data.v_int: %i \n", len_param.data.v_int);
The type of len_param is as follow:
struct Parameter {
enum {
NORMAL, ARRAY, SKIP,
} type;
GIDirection direction;
GIArgument data;
};
And GIArgument definition:
union _GIArgument
{
gboolean v_boolean;
gint8 v_int8;
guint8 v_uint8;
gint16 v_int16;
guint16 v_uint16;
gint32 v_int32;
guint32 v_uint32;
gint64 v_int64;
guint64 v_uint64;
gfloat v_float;
gdouble v_double;
gshort v_short;
gushort v_ushort;
gint v_int;
guint v_uint;
glong v_long;
gulong v_ulong;
gssize v_ssize;
gsize v_size;
gchar * v_string;
gpointer v_pointer;
};
typedef _GIArgument GIArgument;
The complete file can be found here: https://gist.github.com/romgrk/642388914a9ff412eb5683fca44009d7#file-function-cc-L255
And my GDB output when I step at that line is:
Thread 1 "node" hit Breakpoint 1, GNodeJS::FunctionInvoker (info=...) at ../src/function.cc:256
256 len_param.data.v_int = GetV8ArrayLength(info[in_arg]);
(gdb) step
GNodeJS::GetV8ArrayLength (value=...) at ../src/function.cc:25
25 static int GetV8ArrayLength (Local<Value> value) {
(gdb) finish
Run till exit from #0 GNodeJS::GetV8ArrayLength (value=...) at ../src/function.cc:25
GNodeJS::FunctionInvoker (info=...) at ../src/function.cc:260
260 callable_arg_values[length_i].v_pointer = &len_param.data;
Value returned is $1 = 4
(gdb) p len_param.data.v_int
$2 = -17928
(gdb) p len_param
$3 = {
type = GNodeJS::Parameter::SKIP,
direction = GI_DIRECTION_INOUT,
data = {
v_boolean = -17928,
v_int8 = -8 '\370',
v_uint8 = 248 '\370',
v_int16 = -17928,
v_uint16 = 47608,
v_int32 = -17928,
v_uint32 = 4294949368,
v_int64 = 140737488337400,
v_uint64 = 140737488337400,
v_float = -nan(0x7fb9f8),
v_double = 6.9533558069492434e-310,
v_short = -17928,
v_ushort = 47608,
v_int = -17928,
v_uint = 4294949368,
v_long = 140737488337400,
v_ulong = 140737488337400,
v_ssize = 140737488337400,
v_size = 140737488337400,
v_string = 0x7fffffffb9f8 "\t\357\304\303J\a",
v_pointer = 0x7fffffffb9f8
}
}
The problem might be that nothing is ever done with len_param.data except to take its address just before it goes out of scope and the lifetime of len_param expires. So the compiler figures there's no point storing anything there.
Here's the code snippet where len_param is defined, used and dies (with unnecessary code elided and some annotation comments added):
if (param.type == Parameter::ARRAY) {
// ...
Parameter len_param = call_parameters[length_i]; // len_param is defined
if (len_param.direction == GI_DIRECTION_IN) {
// ...
}
else if (len_param.direction == GI_DIRECTION_INOUT) {
len_param.data.v_int = GetV8ArrayLength(info[in_arg]);
callable_arg_values[length_i].v_pointer = &len_param.data;
}
} // len_param goes out of scope, so it's no longer alive
// and the pointer that got placed in `callable_arg_values[length_i].v_pointer`
// is pointing to garbage
The root problem is that the pointer in callable_arg_values[length_i].v_pointer isn't valid moments after it gets stored.

The param was changed by passed to a function when I call the function

The function is defined like this:
1 db_bool cm_text_equal(const cm_text_t *text1, const cm_text_t *text2, db_bool case_ins)
and it will be called like this:
cm_format_element_t * cm_fetch_fmt_element(cm_text_t * fmt)
{
db_uint32 i;
cm_text_t cmp_text;
CM_POINTER(fmt);
cmp_text.str = fmt->str;
for(i = 0; i < DATE_FORMAT_COUNT; i++)
{
cmp_text.len = g_fmt_elements[i].name.len;
if(cmp_text.len > fmt->len)
{
continue;
}
//2 the problem happens here where the function be called
if(cm_text_equal(&g_fmt_elements[i].name, &cmp_text, DB_TRUE))
{
fmt->str += cmp_text.len;
fmt->len = (db_uint16)(fmt->len - cmp_text.len);
return &g_fmt_elements[i];
}
}
return NULL;
}
the g_fmt_elements[] is defined like this:
cm_format_element_t g_fmt_elements[DATE_FORMAT_COUNT] =
{
{{1, (db_char *)" "}, FMT_SPACE_SPLIT, DB_TRUE},
{{1, (db_char *)"-"}, FMT_MINUS_SPLIT, DB_TRUE},
...
}
typedef struct tagcm_format_element
{
cm_text_t name;
db_uint16 id;
db_bool reverse_used;
}cm_format_element_t;
typedef struct tagcm_text
{
db_uint32 len;
db_char * str;
}cm_text_t;
I debug the program by gdb. so before the function cm_text_equal called. the threee parameters are:
&g_fmt_elements[i].name = (cm_text_t *) 0x7f24f8766890
&cmp_text=0x7f2553ef8790
DB_TRUE=1
when cm_fetch_fmt_element is running to the line "//2 the problem...".
the i=30. and the variable g_fmt_elements is a global static variable.
you can see its definition below.
(gdb) p g_fmt_elements[30]
$57 = {name = {len = 4, str = 0x7f24f854a949 "YYYY"}, id = 226, reverse_used = 1}
(gdb) p &g_fmt_elements[30]
$58 = (cm_format_element_t *) 0x7f24f8766890
Then I step into the function cm_text_equal, and it turns out:
(gdb) s
cm_text_equal (text1=0x7f256ec655d0, text2=0x7f2553ef8790, case_ins=1) at src/db_text.c:504
so you can see, the first param was changed from 0x7f24f8766890 to 0x7f256ec655d0, and I check the regesters:
(gdb) p/x $rdi
$52 = 0x7f256ec655d0
(gdb) p/x $rsi
$53 = 0x7f2553ef8790
(gdb) p/x $rdx
$54 = 0x1
you can see the first param passed into the rdi was real changed. Does anyone know how that happend?
I also checked two different addrs.
(gdb) p *(cm_format_element_t*)0x7f256ec655d0
$55 = {name = {len = 4, str = 0x7f256ea6275c "YYYY"}, id = 226, reverse_used = 0}
(gdb) p *(cm_format_element_t*)0x7f24f8766890
$56 = {name = {len = 4, str = 0x7f24f854a949 "YYYY"}, id = 226, reverse_used = 1}
you see, 0x7f24f8766890 is the right addr and its value is the same as definition. while the other addr 0x7f256ec655d0 is wrong, but I don't understand its value almost the same as the right one. However the last member is wrong, which makes my program runs abnormally.
here is more details that I found later
thank you all for trying to help.
I guess I found where to be wrong.
It almost took me two days to figure out the reason, I am not good at. Haha.
but I just still want to answer it for others who may have the same problems.
Ok, let's begin.
Because I have restart my program, so the addr have changed. so this time
before step into the function. the add of g_fmt_elements[30] is:
(gdb) p g_fmt_elements[30]
$6 = {name = {len = 4, str = 0x2ae97faa554e "YYYY"}, id = 226, reverse_used = 1}
(gdb) p &g_fmt_elements[30]
$7 = (cm_format_element_t *) 0x2ae97fcc34d0
(gdb)
and after step into the function, the param text1 become to :
(gdb) cm_text_equal (text1=0x2ae90be468f0, text2=0x2ae926d85540, case_ins=1) at src/db_text.c:499
so, you see, the (cm_format_element_t *) 0x2ae97fcc34d0 seems to changed to text1=0x2ae90be468f0, so I also check these two addr's context:
//-->the right one
(gdb)p *(cm_format_element_t*)0x2ae97fcc34d0
{name = {len = 4, str = 0x2ae97faa554e "YYYY"}, id = 226, reverse_used = 1}
//-->the wrong one
(gdb)p *(cm_format_element_t*)0x2ae90be468f0
{name = {len = 4, str = 0x2ae90bc432e6"YYYY"}, id = 226, reverse_used = 0}
the two's context almost same but the values of "addr of str" and "reverse_used".
so, how exactly the wrong addr 0x2ae90be468f0 comes, and why the context is almost the same?
so, info the libs addr of the program and found which lib does the addr 0x2ae90be468f0 belonged to.

std::list copy to std::vector skipping elements

I've run across a rather bizarre exception while running C++ code in my objective-C application. I'm using libxml2 to read an XSD file. I then store the relevant tags as instances of the Tag class in an std::list. I then copy this list into an std::vector using an iterator on the list. However, every now and then some elements of the list aren't copied to the vector. Any help would be greatly appreciated.
printf("\n length list = %lu, length vector = %lu\n",XSDFile::tagsList.size(), XSDFile::tags.size() );
std::list<Tag>::iterator it = XSDFile::tagsList.begin();
//result: length list = 94, length vector = 0
/*
for(;it!=XSDFile::tagsList.end();++it)
{
XSDFile::tags.push_back(*it); //BAD_ACCESS code 1 . . very bizarre . . . . 25
}
*/
std::copy (XSDFile::tagsList.begin(), XSDFile::tagsList.end(), std::back_inserter (XSDFile::tags));
printf("\n Num tags in vector = %lu\n", XSDFile::tags.size());
if (XSDFile::tagsList.size() != XSDFile::tags.size())
{
printf("\n length list = %lu, length vector = %lu\n",XSDFile::tagsList.size(), XSDFile::tags.size() );
//result: length list = 94, length vector = 83
}
I've found the problem. The memory was corrupted causing the std::list to become corrupted during the parsing of the XSD. I parse the XSD using a function start_element.
xmlSAXHandler handler = {0};
handler.startElement = start_element;
I used malloc guard in xcode to locate the use of freed memory. It pointed to the line:
std::strcpy(message, (char*)name);
So I removed the malloc (actually commented in the code) and it worked. The std::vector now consistently copies all 94 entries of the list. If anyone has an explanation as to why this worked that would be great.
static void start_element(void * ctx, const xmlChar *name, const xmlChar **atts)
{
// int len = strlen((char*)name);
// char *message = (char*)malloc(len*sizeof(char));
// std::strcpy(message, (char*)name);
if (atts != NULL)
{
// atts[0] = type
// atts[1] = value
// len = strlen((char*)atts[1]);
// char *firstAttr = (char*)malloc(len*sizeof(char));
// std::strcpy(firstAttr, (char*)atts[1]);
if(strcmp((char*)name, "xs:include")==0)
{
XSDFile xsd;
xsd.ReadXSDTypes((char*)atts[1]);
}
else if(strcmp((char*)name, "xs:element")==0)
{
doElement(atts);
}
else if(strcmp((char*)name, "xs:sequence")==0)
{
//set the default values
XSDFile::sequenceMin = XSDFile::sequenceMax = 1;
if (sizeof(atts) == 4)
{
if(strcmp((char*)atts[3],"unbounded")==0)
XSDFile::sequenceMax = -1;
int i = 0;
while(atts[i] != NULL)
{
//atts[i] = name
//atts[i+i] = value
std::string name((char*)atts[i]);
std::string value((char*)atts[i+1]);
if(name=="minOccurs")
XSDFile::sequenceMin = (atoi(value.c_str()));
else if(name=="maxOccurs")
XSDFile::sequenceMax = (atoi(value.c_str()));
i += 2;
}
}
}
}
//free(message);
}

Linked list sorting function in C++ doesn't stop properly

Many thanks in advance!
So, I've made attempts to make this function work. There are mistakes in the function but cannot catch them.
It seems to me, that I've missed the logic of sorting.
Could you point me 'where to go'?
/* node*/
typedef struct client {
int number; /* */
int balance;/* */
char lastName[20]; /* */
char firstName [20];/* */
char phone[11]; /* */
char email[20];
struct client *prev;/* */
struct client *next;
struct client *tmp; /* */
} Client;
Client *firstc,*currentc,*newc, *a, *b,*tmp; /*pointers*/
/* *"firstc' firstc element in list
*'currentc' current node
*'newc' new node
*'a' temporary pointer to Sort function
*'b' temporary pointer to Sort function
*'tmp' temporary pointer to Sort function
*/
int counter = 0;
int cnum = 0; /*cnum gives unique account numbers avoiding misentering*/
/*---Sort function------*/
void Sort()
{
/* */
int a = 0;/*variables to store balance*/
int b = 0;/*variables to store balance*/
if(firstc==NULL)
printf("Database is empty"); /*message*/
else
currentc = firstc;
currentc->prev = NULL;
tmp = NULL;
while((currentc=currentc->next)!= NULL)
{ /* 1) compare two nodes;
2) IF balance >*/
int a = currentc->balance;
int b = currentc->next->balance;/* debugger stopped here... */
if (a>b)
//if(currentc->balance >currentc->next->balance)
{ /*swap nodes*/
/*code using three pointers*/
tmp = currentc->next;
currentc->next->next = currentc->next;
currentc->next->next = tmp;
}
/*3)move along the list*/
else
currentc = currentc->next;
/*4) repeat to the end of list*/
}
currentc = firstc;
listAll();
return;
}
int b = currentc->next->balance;/* debugger stopped here... */
When currentc is pointing to the last item in the list currentc->next will be null. So currentc->next->balance is an access through a null pointer.
Also, practices like making assignments in conditions like while((currentc=currentc->next)!= NULL) will eventually come back to hurt you. In this case it seems you are skipping the first item in the list.
You probably meant:
if(firstc == NULL)
printf("Database is empty"); /*message*/
else
{ /* missing braces spotted by others */
currentc = firstc;
currentc->prev = NULL;
tmp = NULL;
for( ; currentc != NULL; currentc = currentc->next)
{
if(currentc->next == NUL)
/* nothing to compare */
break;
...
}
}
Furthermore the swapping code is swapping the wrong nodes:
tmp = currentc->next;
currentc->next->next = currentc->next;
currentc->next->next = tmp;
will almost (but not quite) swap the next node (b), with the one after it instead of with (a). You need to use the prev pointer (However since this looks like homework I had better not tell you exactly how to do it). Also, you are initialising prev but you need to keep it up to date in the loop. Actually, your 3 lines above are equivalent to:
tmp = currentc->next;
currentc->next->next = tmp;
so I think you meant something else.
the problem is when currentc is the last node, currectc->next is null, thus currentc->next->balance make it crash.
add some validation like
if (currentc->next == null)
and set b to a default/predefined value or put some logic whether you swap the nodes or not.