Hello,I found out while single stepping a new template function in gdb that gcc generates bad/inaccurate line numbers in the debug info. Optimization was turned off, but the execution jumped strangely, see below. gcc-4.4 and the current clang produced the expected results, gcc 4.5, 4.6, 4.7, 4.8 all had problems. The code was factored out from a proof-of-concept hack.
Here is the trace that was produced in gdb by single stepping the program with 'n'. The program was compiled w/ gcc 4.8.0 git commit e7ae865c:
COLLECT_GCC=gcc-4.8.0 COLLECT_LTO_WRAPPER=/home/usr-local/bin/../libexec/gcc/x86_64-unknown-linux-gnu/4.8.0/lto-wrapper Target: x86_64-unknown-linux-gnuConfigured with: ./configure --enable-languages=c,c++ --program-suffix=-4.8.0
Thread model: posix gcc version 4.8.0 20120605 (experimental) (GCC) g++-4.8.0 -g -O0 -Wall -Wextra -o dbginfobug.o -c dbginfobug.cpp g++-4.8.0 -g -o dbginfobug dbginfobug.o 11 while (C c = *f++) { 12 if (c == '$') { 56 if (o < e) { 57 *o = c; 59 ++o;// the first anomaly: the line printed is AFTER the loop, while we're still in the loop
// this happens only with 4.8, after each iteration 62 printf("RESULT (%zu chars): '%s'\n", o - buf, buf); 11 while (C c = *f++) { 12 if (c == '$') { 56 if (o < e) { 57 *o = c; 59 ++o; 62 printf("RESULT (%zu chars): '%s'\n", o - buf, buf); ... 62 printf("RESULT (%zu chars): '%s'\n", o - buf, buf); 11 while (C c = *f++) { 12 if (c == '$') { 13 C c2 = *f; 14 if (c2 == '$') { 18 unsigned ai = gai; 19 if (c2 == '{') { 20 ++f; 21 C c3 = *f; 22 if (c3 >= '0' && c3 <= '9') { 23 ai = 0; 24 while (C c4 = *f) {25 if (c4 < '0' || c4 > '9') {
28 ai *= 10; 29 ai += c4 - '0'; 30 ++f; 24 while (C c4 = *f) {25 if (c4 < '0' || c4 > '9') {
// doesn't stop on the break with 4.8, stops with earlier versions// !!! we should be after the closing brace of the loop, yet we're still inside
30 ++f; (gdb) p c4// this is quite a gotcha: c4 of type C is not in the scope anymore, but some constant
// of type mynumber creeps in the scope from libm. // this wasn't too helpful understanding what's going on... $16 = {i = {1431655765, -1079683755}, x = -0.041666666666666664} (gdb) p f $17 = 0x400a18 "}\n" 36 C x = *f++; // f was not incremented (correctly), despite it stood on the line ++f (gdb) p f $18 = 0x400a18 "}\n" 37 if (x == '}') {// now it stops on this break. what's the difference compared to the above if() where it didn't stop?
38 break; 62 printf("RESULT (%zu chars): '%s'\n", o - buf, buf); 11 while (C c = *f++) { 12 if (c == '$') {I attached the cpp source, and also the preprocessed version, if it makes any difference.
I couldn't find anything similar in bz, please let me know whether this is a new issue and I will file a bugreport.
Regards, Peter
#include <stddef.h> #include <stdio.h> template<typename C> void do_print(C* buf, size_t siz, const C* fmt) { const C* f = fmt; C* o = buf; C* e = buf + siz; unsigned gai = 0; while (C c = *f++) { if (c == '$') { C c2 = *f; if (c2 == '$') { ++f; goto lit; } unsigned ai = gai; if (c2 == '{') { ++f; C c3 = *f; if (c3 >= '0' && c3 <= '9') { ai = 0; while (C c4 = *f) { if (c4 < '0' || c4 > '9') { break; } ai *= 10; ai += c4 - '0'; ++f; } } else { ++gai; } do { C x = *f++; if (x == '}') { break; } if (x == 0) { fprintf(stderr, "ERROR: no closing brace\n"); return; } if (x == 'f') { break; } else { fprintf(stderr, "ERROR: invalid format specifier char '%c'\n", x); return; } } while (1); } else { ++gai; } } else { lit: if (o < e) { *o = c; } ++o; } } printf("RESULT (%zu chars): '%s'\n", o - buf, buf); } void foo() { char buf[256]; do_print(buf, sizeof(buf), "T $$ ${1}\n"); } int main() { foo(); }
dbginfobug.E.gz
Description: GNU Zip compressed data