Article View: gnu.gdb.bug
Article #113Gdb 4.6 bug report
From: Douglas Scott
Date: Wed, 22 Jul 1992 23:51
Date: Wed, 22 Jul 1992 23:51
747 lines
19741 bytes
19741 bytes
System: Sun 4/330 Running SunOS 4.1
Compiler: gcc/g++ 2.2.2
Gdb version: 4.6, compiled with GCC_MANGLE_BUG flag
Problems:
1) Gdb will not print value returned from overloaded operator [](int), claiming
structure has no such component (see log).
2) Gdb dumps core when attempting to print return value of a virtual function called
from a reference to an object (see log).
Here is a log of two problems, followed by the code. I
apologize for the length of the code, but it is an extract
from a 14,000 line program, and I couldnt take the time to
strip any more out of it. If it is too long for you to deal
with, let me know, and I will try to extract the problem
part out.
---
Douglas Scott (805)893-8352
Center for Computer Music Research and Composition
University of California, Santa Barbara
Internet: (NeXTMail ok) <doug@foxtrot.ccmrc.ucsb.edu>
######################################################
(gdb) run
Starting program: /home/doug/C++/a.out
Breakpoint 2, Request::retrieveValues (this=0xf7fffbb8, v=@0xf7fffb78)
at testit.c:520
520 v[valsReturned] = *(valueList->value());
(gdb) ptype v
type = class ValueArray {
private:
void *array;
int length_;
int offset;
public:
ValueArray(QueryValue *, int);
struct QueryValue & operator[](int) const;
int length(void) const;
} &
(gdb) print v[valsReturned]
Structure has no component named operator[].
######################################################
gdb a.out
GDB is free software and you are welcome to distribute copies of it
under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.6, Copyright 1992 Free Software Foundation, Inc...
(gdb) break 291
Breakpoint 1 at 0x2a48: file testit.c, line 291.
(gdb) run
Starting program: /home/doug/C++/a.out
Breakpoint 1, QueryValue::operator= (this=0xf7fffb88, rhs=@0x36040)
at testit.c:291
291 set(rhs.value());
Warning: the current language does not match this frame.
(gdb) print rhs
$1 = (struct QueryValue &) @0x36040: {
<QueryLabel> = {
label_ = 0x36060,
_vptr$QueryLabel = 0x32340 <IntValue virtual table>
},
members of QueryValue:
checkFun = 0x3d64 <posNumsOnly(char)>,
legalValue = 0x3e24 <checkDouble(char *)>
}
(gdb) ptype rhs
type = class QueryValue : public QueryLabel {
protected:
int (*checkFun)();
int (*legalValue)();
public:
virtual ~QueryValue(void);
QueryValue(const char *, int (*)(char), int (*)(const char *));
protected:
QueryValue(void);
public:
virtual char * value(void) const;
virtual int intValue(void) const;
virtual double doubleValue(void) const;
virtual int set(const char *);
int (*)() charCheckFunction(void);
protected:
void operator=(const QueryValue &);
private:
virtual int size(void);
} &
(gdb) print rhs.value()
Segmentation fault (core dumped)
tango> gdb ./gdb ~doug/C++/core
GDB is free software and you are welcome to distribute copies of it
under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.6, Copyright 1992 Free Software Foundation, Inc...
Core was generated by `gdb'.
Program terminated with signal 11, Segmentation fault.
#0 0x13f88 in unpack_field_as_long (type=0x136518, valaddr=0xf4630 "",
fieldno=-16) at values.c:1222
1222 memcpy (&val, valaddr + bitpos / 8, sizeof (val));
Setting up the environment for debugging gdb.
Breakpoint 1 at 0x33bd4: file utils.c, line 274.
Breakpoint 2 at 0x4774: file main.c, line 1658.
(top-gdb) bt
#0 0x13f88 in unpack_field_as_long (type=0x136518, valaddr=0xf4630 "",
fieldno=-16) at values.c:1222
#1 0x137d8 in value_primitive_field (arg1=0xf4608, offset=170831022,
fieldno=-1, arg_type=0x136518) at values.c:863
#2 0x138a8 in value_field (arg1=0xf4608, fieldno=-1) at values.c:898
#3 0x13a04 in value_virtual_fn_field (arg1=0xf4608, f=0x136740, j=1271064,
type=0x136518) at values.c:971
#4 0x181d8 in search_struct_method (name=0xf44b0 "value", arg1=0xf4608,
args=0xf7fff6f4, offset=0, static_memfuncp=0xf7fff768, type=0x136518)
at valops.c:1095
#5 0x18690 in value_struct_elt (argp=0xf7fff76c, args=0xf7fff6f4,
name=0xf44b0 "value", static_memfuncp=0xf7fff768, err=0x14928 "structure")
at valops.c:1222
#6 0x15224 in evaluate_subexp (expect_type=0x0, exp=0xf4488, pos=0xf7fff7e4,
noside=EVAL_NORMAL) at eval.c:385
#7 0x148b4 in evaluate_expression (exp=0xf4488) at eval.c:142
#8 0x1fec4 in print_command_1 (exp=0xe600e "rhs.value()", inspect=0,
voidprint=1) at printcmd.c:752
#9 0x20020 in print_command (exp=0xe600e "rhs.value()", from_tty=1)
at printcmd.c:803
#10 0x3930 in execute_command (p=0xe600e "rhs.value()", from_tty=1)
at main.c:915
#11 0x3ae4 in command_loop () at main.c:976
#12 0x3734 in main (argc=2, argv=0xf7fffc54) at main.c:853
////////////////////////// source for gdb test //////////////////////////
#include <String.h>
typedef int (*CharCheckFun)(const char);
typedef int (*LegalValueFun)(const char *);
enum Response {
Cancel = 0, Yes = 1, No = 2
};
class String;
struct QueryLabelInfo {
char *label;
};
struct QueryButtonInfo {
char *label; // label for button
Response response; // behavior for this button (yes, no, cancel)
};
enum ValueType { None, VString, VInt, VDouble };
struct QueryValueInfo {
ValueType type;
char *label;
char *defaultVal;
CharCheckFun check;
LegalValueFun legal;
};
struct QueryInfo {
QueryLabelInfo *labelInfo;
char *valueListLabel;
QueryValueInfo *valueInfo;
QueryButtonInfo *buttonInfo;
};
// base class for all query items, and also used for plain labels
class QueryLabel {
public:
QueryLabel(const char *);
virtual ~QueryLabel();
const char* label();
private:
String *label_;
};
// class for response buttons (confirm, cancel, etc.)
class QueryButton : public QueryLabel {
public:
QueryButton(const char *, Response resp=Yes);
virtual ~QueryButton();
virtual Response response() { return response_; }
virtual int set(Response r) { response_ = r; return 1; }
private:
Response response_;
};
class ValueArray;
// class for querying string, int, or double values
class QueryValue : public QueryLabel {
public:
QueryValue(const char *, CharCheckFun ccf, LegalValueFun lvf);
virtual ~QueryValue();
virtual const char* value() const = 0;
virtual const int intValue() const = 0;
virtual const double doubleValue() const = 0;
virtual int set(const char *) = 0;
CharCheckFun charCheckFunction() { return checkFun; }
void operator = (const QueryValue& rhs);
protected:
QueryValue();
CharCheckFun checkFun;
LegalValueFun legalValue;
private:
friend ValueArray;
virtual int size() { return sizeof(*this); }
};
class StringValue : public QueryValue {
public:
StringValue(const char *, const char *, CharCheckFun ccf, LegalValueFun lvf);
StringValue(const char *value=0);
virtual ~StringValue();
virtual const char* value() const;
virtual const int intValue() const;
virtual const double doubleValue() const;
virtual int set(const char *);
private:
friend ValueArray;
virtual int size() { return sizeof(*this); }
String *string;
};
class IntValue : public QueryValue {
public:
IntValue(const char *, const int, CharCheckFun ccf, LegalValueFun lvf);
IntValue(int value=0);
virtual ~IntValue();
virtual const char* value() const;
virtual const int intValue() const;
virtual const double doubleValue() const;
virtual int set(const char *);
private:
friend ValueArray;
virtual int size() { return sizeof(*this); }
int value_;
};
class DoubleValue : public QueryValue {
public:
DoubleValue(const char *, const double, CharCheckFun ccf, LegalValueFun
lvf);
DoubleValue(double value=0.0);
virtual ~DoubleValue();
virtual const char* value() const;
virtual const int intValue() const;
virtual const double doubleValue() const;
virtual int set(const char *);
private:
friend ValueArray;
virtual int size() { return sizeof(*this); }
double value_;
};
// this allows me to create a virtual array, i.e., it fixes the problem with
// the array index not adding the correct offset for the derived virtual class
class ValueArray {
public:
ValueArray(QueryValue *qa, int len) : array(qa), length_(len) {
offset = qa->size();
}
QueryValue & operator [] (int index) const {
// check index and return reference to the base class
index = index < length_ ? index : length_ - 1;
return *((QueryValue *)(array + offset * index));
}
int length() const { return length_; }
private:
void *array; // raw pointer to beginning of array
int length_;
int offset; // the proper size of each array element
};
class QueryLabel;
struct QueryLink {
QueryLink(QueryLabel *q);
virtual ~QueryLink();
QueryLabel *element;
QueryLink *next;
};
class String;
// linked list container/manipulator for QueryLabel and its derived classes
class QueryList {
public:
QueryList(const char *lbl);
virtual ~QueryList();
void append(QueryLabel *);
void start() { current = head; }
int more() { return current != 0; }
void next() { current = current->next; }
const char *label();
QueryLabel *value() { return current->element; }
private:
QueryLink *tail();
private:
String *listLabel;
QueryLink *current;
QueryLink *head;
};
class QueryButton;
class ButtonList : public QueryList {
public:
ButtonList(const char *lbl=0) : (lbl ? lbl : "") {}
virtual ~ButtonList() {}
QueryButton *value() { return (QueryButton *) QueryList::value(); }
};
class QueryValue;
class ValueList : public QueryList {
public:
ValueList(const char *lbl=0) : (lbl ? lbl : "") {}
virtual ~ValueList() {}
QueryValue *value() { return (QueryValue *) QueryList::value(); }
};
enum RequestType { AlertType, ConfirmerType, ChoiceType, InputType };
class DialogConstructor;
class ValueArray;
class Request {
friend DialogConstructor;
public:
Request() { init(); }
Request(QueryInfo *);
virtual ~Request();
int hasLabels() { return labelList != 0; }
int hasValues() { return valueList != 0; }
int useBell() { return bell; }
virtual RequestType type() { return InputType; }
// default
void appendLabel(const char *);
void appendValue(const char *, const char *value, CharCheckFun,
LegalValueFun);
void appendValue(const char *, int value, CharCheckFun,
LegalValueFun);
void appendValue(const char *, double value, CharCheckFun,
LegalValueFun);
void appendValue(ValueType, const char *, const char *,
CharCheckFun ccf, LegalValueFun lvf);
void appendButton(const char *, Response);
void retrieveValues(ValueArray &v);
protected:
virtual void createLabelList(QueryLabelInfo *);
virtual void createValueList(const char *, QueryValueInfo *);
virtual void createButtonList(QueryButtonInfo *);
void setBell(int b) { bell = b; }
protected:
QueryList *labelList;
ValueList *valueList;
ButtonList *buttonList;
private:
void init();
private:
int bell; // flag for bell ring
};
QueryLabel::QueryLabel(const char* lbl) {
label_ = new String(lbl);
}
QueryLabel::~QueryLabel() {
delete label_;
}
const char*
QueryLabel::label() { return *label_; }
/////////
QueryButton::QueryButton(const char *lbl, Response r) : (lbl), response_(r) {}
QueryButton::~QueryButton() {}
/////////
// default functions for QueryValue
static int anychar(const char c) { return 1; }
static int anyvalue(const char *v) { return 1; }
QueryValue::QueryValue(const char* lbl, CharCheckFun ccf, LegalValueFun lvf)
: (lbl), checkFun(ccf), legalValue(lvf) {}
QueryValue::QueryValue() : (""), checkFun(anychar), legalValue(anyvalue) {}
QueryValue::~QueryValue() {}
void
QueryValue::operator = (const QueryValue& rhs) {
// this allows any of the derived classes to be assigned to any other
// via use of character strings passed between virtual functions
set(rhs.value());
}
/////////
StringValue::StringValue(const char *lbl, const char *s, CharCheckFun ccf,
LegalValueFun lvf) : (lbl, ccf, lvf) {
string = new String(s ? s : "");
}
StringValue::StringValue(const char *value) {
string = new String(value ? value : "");
}
StringValue::~StringValue() {
delete string;
}
int
StringValue::set(const char *s) {
register int good = 0;
if(good = legalValue(s)) {
*string = (s && strlen(s)) ? s : "0";
}
return good;
}
const char *
StringValue::value() const {
return *string;
}
int
StringValue::intValue() const {
return atoi(strlen(*string) > 0 ? *string : "0");
}
double
StringValue::doubleValue() const {
return atof(strlen(*string) > 0 ? *string : "0");
}
IntValue::IntValue(const char *lbl, const int i, CharCheckFun ccf,
LegalValueFun lvf) : (lbl, ccf, lvf), value_(i) {}
IntValue::IntValue(int value) : value_(value) {}
IntValue::~IntValue() {}
const char *
IntValue::value() const {
static char string[64];
sprintf(string, "%d", value_);
return string;
}
int
IntValue::intValue() const {
return value_;
}
double
IntValue::doubleValue() const {
return value_;
}
int
IntValue::set(const char *s) {
register int good = 0;
if(good = legalValue(s)) {
value_ = (s && strlen(s)) ? atoi(s) : 0;
}
return good;
}
DoubleValue::DoubleValue(const char *lbl, const double d, CharCheckFun ccf,
LegalValueFun lvf) : (lbl, ccf, lvf), value_(d) {}
DoubleValue::DoubleValue(double value) : value_(value) {}
DoubleValue::~DoubleValue() {}
const char *
DoubleValue::value() const {
static char string[128];
sprintf(string, "%f", value_);
return string;
}
int
DoubleValue::intValue() const {
return int(value_);
}
double
DoubleValue::doubleValue() const {
return value_;
}
int
DoubleValue::set(const char *s) {
register int good = 0;
if(good = legalValue(s)) {
value_ = (s && strlen(s)) ? atof(s) : 0;
}
return good;
}
QueryLink::QueryLink(QueryLabel *q) {
element = q;
next = 0;
}
QueryLink::~QueryLink() { delete element; }
QueryList::QueryList(const char *label) {
listLabel = new String(label);
head = 0;
}
QueryList::~QueryList() {
delete listLabel;
start();
while(current) {
register QueryLink *next = current->next;
delete current;
current = next;
}
}
QueryLink *
QueryList::tail() {
start();
while(current && current->next)
current = current->next;
return current;
}
void
QueryList::append(QueryLabel *q) {
register QueryLink *link = new QueryLink(q);
if(!head)
head = link;
else
tail()->next = link;
current = link;
}
const char *
QueryList::label() { return *listLabel; }
////////
Request::Request(QueryInfo *qinfo) {
init();
if(qinfo->labelInfo)
createLabelList(qinfo->labelInfo);
if(qinfo->valueInfo)
createValueList(qinfo->valueListLabel, qinfo->valueInfo);
if(qinfo->buttonInfo)
createButtonList(qinfo->buttonInfo);
}
void
Request::init() {
labelList = 0;
valueList = 0;
buttonList = 0;
bell = 0;
}
Request::~Request() {
delete labelList;
delete valueList;
delete buttonList;
}
void
Request::appendLabel(const char *lbl) {
if(!labelList) labelList = new QueryList("");
labelList->append(new QueryLabel(lbl));
}
void
Request::appendButton(const char *lbl, Response response) {
if(!buttonList) buttonList = new ButtonList;
buttonList->append(new QueryButton(lbl, response));
}
void
Request::appendValue(const char *label, const char *value, CharCheckFun ccf,
LegalValueFun lvf) {
if(!valueList) valueList = new ValueList;
valueList->append(new StringValue(label, value, ccf, lvf));
}
void
Request::appendValue(const char *label, int value, CharCheckFun ccf,
LegalValueFun lvf) {
if(!valueList) valueList = new ValueList;
valueList->append(new IntValue(label, value, ccf, lvf));
}
void
Request::appendValue(const char *label, double value, CharCheckFun ccf,
LegalValueFun lvf) {
if(!valueList) valueList = new ValueList;
valueList->append(new DoubleValue(label, value, ccf, lvf));
}
void
Request::appendValue(ValueType type, const char *label, const char *defval,
CharCheckFun ccf, LegalValueFun lvf) {
if(!valueList) valueList = new ValueList;
valueList->append(
type == VString ? new StringValue(label, defval, ccf, lvf)
: type == VInt ? new IntValue(label, atoi(defval), ccf, lvf)
: new DoubleValue(label, atof(defval), ccf, lvf)
);
}
void
Request::retrieveValues(ValueArray &v) {
int valsReturned = 0, nvals = v.length();
if(hasValues()) {
for(valueList->start();
valueList->more() && valsReturned != nvals;
valueList->next(), ++valsReturned) {
v[valsReturned] = *(valueList->value());
}
}
}
void
Request::createLabelList(QueryLabelInfo *qlist) {
for(QueryLabelInfo *i = qlist; i->label != 0; i++) {
appendLabel(i->label);
}
}
void
Request::createButtonList(QueryButtonInfo *qbilist) {
for(QueryButtonInfo *i = qbilist; i->label != None; i++) {
appendButton(i->label, i->response);
}
}
void
Request::createValueList(const char *vlistlabel, QueryValueInfo *qvilist) {
valueList = new ValueList(vlistlabel);
for(QueryValueInfo *i = qvilist; i->type != None; i++) {
appendValue(i->type, i->label, i->defaultVal, i->check,
i->legal);
}
}
// here are the char test functions for checking user input
int
posIntsOnly(char c) { // control chars and integers only
return (iscntrl(c) || isdigit(c));
}
int
intsOnly(char c) {
return (c == '-' || posIntsOnly(c));
}
int
posNumsOnly(char c) { // control chars, '.', and integers only
return (c == '.' || posIntsOnly(c));
}
int
numsOnly(char c) {
return (c == '.' || intsOnly(c));
}
int
checkDouble(char *s) {
return 1;
}
static QueryButtonInfo defaultInputButtonInfo[] = {
{ "confirm", Yes },
{ "cancel", Cancel },
{ 0 }
};
main() {
static QueryLabelInfo labels[] = {
{ "Set Endpoints for Horizontal Display: " }, { 0 }
};
static QueryInfo info[] = {
labels, "", 0, defaultInputButtonInfo
};
int start = 0;
int end = 50;
// create and load a Request object with default values
Request request(info);
request.appendValue("Minimum Samp: ", start, posNumsOnly, checkDouble);
request.appendValue("Maximum Samp: ", end, posNumsOnly, checkDouble);
// normally at this point, the request object would be passed to a
// dialog creation and display object that queries the user for input
const int nvals = 2;
IntValue vr[nvals];
// now get the newly set values and load them into vr[]
// (in this case they are still set to the default values)
request.retrieveValues(ValueArray(vr, nvals));
printf("Values retrieved are %d and %d\n",
vr[0].intValue(), vr[1].intValue());
}
Technical Details
Message-ID:
<9207222351.AA18283@foxtrot.ccmrc.ucsb.edu>Path:
arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!foxtrot.ccmrc.ucsb.edu!dougShow Full Headers
Complete Article Headers
Newsgroups: gnu.gdb.bug Path: arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!foxtrot.ccmrc.ucsb.edu!doug From: doug@foxtrot.ccmrc.ucsb.edu (Douglas Scott) Subject: Gdb 4.6 bug report Message-ID: <9207222351.AA18283@foxtrot.ccmrc.ucsb.edu> Sender: gnulists@ai.mit.edu Organization: GNUs Not Usenet Distribution: gnu Date: Wed, 22 Jul 1992 23:51:03 GMT Approved: bug-gdb@prep.ai.mit.edu Lines: 748