Quote:
221 num.assign(dbyte, L"asdf = %u xyz"); Current language: auto; currently c++ (gdb) p &num $10 = (SysString *) 0x7fbfffe2a0 (gdb) p num.value_d $1 = (unichar *) 0x61fcb0 (gdb) s SysString::assign (this=0x7f00000000, arg_a=27 '\033', fmt_a=0x41afd8) at sstr_03.cc:818 818 bool8 SysString::assign(byte8 arg_a, const unichar* fmt_a) { (gdb) p this $2 = (SysString * const) 0x7f00000000 (gdb) p &value_d $3 = (unichar **) 0x7f00000000 (gdb) p this->value_d $4 = (unichar *) 0x0 (gdb) s 828 if (fmt_a == (unichar*)NULL) { (gdb) p this $5 = (SysString * const) 0x7f00000000 (gdb) p &value_d $6 = (unichar **) 0x7f00000000 (gdb) p this->value_d $7 = (unichar *) 0x0 (gdb) Now what? Should not &num and this point to the same memory? |
That's a bit of a surprise. 0x7f00000000 seems to be a valid address.
So that makes the original seg fault less plausible. Your post #9 makes it look like there was a seg fault at Code:
SysString::clear (this=0x7f00000000, cmode_a=Integral::RESET) at sstr_03.cc:1623 The latter should be easy to determine by just setting a breakpoint there and proceeding to it and seeing what this and capacity_d and &capacity_d all are. Assuming GDB might be wrong about the line number of the seg fault, we'd also like to know what value_d is at that point. Edit: Sorry, I wasn't thinking clearly. We already know value_d was bad before it reached there, so we can reasonably assume GDB is wrong about the line number of the seg fault and you need to look earlier not later to find out when/why value_d was clobbered. |
Quote:
the address of num is 0x7fbfffe2a0 and just after calling it changes What kind of things could do this? |
Quote:
Now, I assume you showed us that because you think num at line sstr_02.cc:221 is the same object as *this at line sstr_03.cc:818. So you should validate that by having gdb give the vale of &num at line sstr_02.cc:221 Edit: you answered that while I was asking the question. |
Quote:
Quote:
That is exactly the kind of bug typical of an error in porting 32 bit code to 64 bit. This could easily be caused by the immediately preceding object in memory being stored as 64 bits into a 32 bit allocated space overwriting the next 32 bits with zero. Note I mean the object preceding the pointer to num, not the object preceding num itself. I could be a lot more specific if I saw all the code from the declaration of num through line 221. |
Quote:
Breakpoint 1, SysString::diagnose (level_a=Integral::BRIEF) at sstr_02.cc:221 221 num.assign(dbyte, L"asdf = %u xyz"); (gdb) p &num $3 = (SysString *) 0xbfffebc4 (gdb) s SysString::assign (this=0xbfffebc4, arg_a=27 '\033', fmt_a=0x8063ac0 L"asdf = %u xyz") at sstr_03.cc:828 828 if (fmt_a == (unichar*)NULL) { (gdb) p this $4 = (SysString * const) 0xbfffebc4 (gdb) so &num and this are the same on 64bit: Breakpoint 1, SysString::diagnose (level_a=<value optimized out>) at sstr_02.cc:221 221 num.assign(dbyte, L"asdf = %u xyz"); (gdb) p &num $15 = (SysString *) 0x7fbfffe2a0 (gdb) s SysString::assign (this=0x7f00000000, arg_a=27 '\033', fmt_a=0x41afd8) at sstr_03.cc:818 818 bool8 SysString::assign(byte8 arg_a, const unichar* fmt_a) { (gdb) p this $16 = (SysString * const) 0x7f00000000 (gdb) This shows that the address for num has changed , right? |
Quote:
|
Quote:
Code:
// make sure that an empty string fails |
That makes it look like the call to num.get(dbyte_v); did the harm.
Is the source code to get posted yet? num is a local variable in the current stack frame. GDB deduces its address (at line 221) from the rbp register. That register must not be corrupted or gdb would be totally confused at that point. The only way to get this symptom is if the optimizer had put the address of num into a callee saved register (because it is used so much) rather than recompute it from ebp each time. That's strange because recomputing it from ebp is nearly free compared to simply copying it into edi (all that would make sense if you knew x86_64 asm). |
Quote:
Code:
// method: get |
I'm pretty sure this is the bug:
Code:
uint32 val = 0; val is only 32 bits. If you don't understand, post the definition of DEF_FMT_LONG_8BIT and I can explain more specifically. In architectures where uint32 is the same size as long, this code works. In architectures where long is bigger, this code clobbers the low half of a register saved by the entry into this function. It then returns to the caller with the wrong value in a register. Whether/how that matters depends on details of the optimization in that calling function. As I started to explain in post #24, I had deduced that the optimizer placed an extra copy of the address of num in a callee saved register that happens to be the register clobbered by the bug in get. |
// constants: 8-bit version of the default format strings (for efficiency)
// const char SysString::DEF_FMT_VOIDP_8BIT[] = "%p"; const char SysString::DEF_FMT_ULONG_8BIT[] = "%lu"; could it be the problem? Actually your comment make sense to me but I wonder if this could make segmentation fault? |
I think I can correct this part and then I will report the result here, thanks your comment is really make sense now after some thinking ;)
|
Quote:
DEF_FMT_LONG_8BIT, but you posted two other format strings. Anyway, this is the problem. There is a similar problem in more than one of your overloads of get. So fix it in each place, not just in the one that is causing this specific seg fault. |
Quote:
|
All times are GMT -5. The time now is 02:10 AM. |