51
\$\begingroup\$

It seems that simple changes to a C++ file, especially with templates, can generate pages of errors. This contest is to see what the largest "bang of the buck" is, that is the more verbose error output with the smallest change to the source code (1 character addition).

Because other languages are more sane, this will be limited to C++ and gcc version 4.x.

Rules

  1. Original source file must compile with gcc 4.9.2 to object code without error.

  2. One ASCII character is added to source code to create a typo, increasing file size by 1 byte.

  3. Compiler is run with default options. Necessary options like -c and -std=c++11 are allowed, options like -Wall are not.

  4. Metric is

        number of bytes of generated error messages
        -----------------------------------------------------------------------
        (bytes of source code with typo) (length of filename passed to compiler)
    
  5. Answers will be validated with http://ideone.com/ C++ 4.9.2.

Example:

Filename is a.cpp, which is 5 bytes long.

int foo();

Working Compilation

 gcc -c a.cpp

Corrupted source code:

in t foo();

Failing Compilation

$ gcc -c a.cpp
a.cpp:1:1: error: ‘in’ does not name a type
in t foo();
  ^
$ gcc -c a.cpp |& -c wc
64
$ wc -c a.cpp
12 a.cpp

Score: 64/12/5 = 1.0666

Better attempt: Insert { between parens of foo()

$ gcc -c a.cpp |& wc -c
497

New score: 497/12/5 = 8.283

Good Luck!

UPDATE

I encourage people to ignore the recursive implementation. That technically wins but is not in the spirit of the contest.

UPDATE 2

As many people have noted, the contest probably would have been more interesting if the C pre-processor was not allowed. So I would like to encourage people to post solutions that do not use pre-processor commands at all. That implies no use of any header files at all, since #include is not allowed!

As far as using IDEONE to validate, you are allowed to either use the IDEONE output directly (and the source name as prog.cpp), or you can run the IDEONE output through a global search and replace (s/prog.cpp/a.cc/ for example) and pretend that you were able to set the file name directly.

UPDATE 3

As people pointed out, Ideone is a little too restrictive, requiring linkage not just object file creation. As this contest is purely in the name of fun, please be honest and specify what you used to get your score. Either use ideone, or use the most vanilla build (all defaults) of gcc 4.9.2 as you can muster. The contest is intended to bring awareness to the awfulness of C++ error messages.

\$\endgroup\$
  • \$\begingroup\$ Comments are not for extended discussion; this conversation has been moved to chat. Alternatively, for discussions about what should or shouldn't count as a duplicate please take the discussion to meta. \$\endgroup\$ – Martin Ender Jun 13 '15 at 21:18
  • \$\begingroup\$ Three issues with using ideone to validate: It forces source file name to "prog.cpp", it truncates compiler error output to 64kB, and it links, adding extra errors. So it won't be a good validation tool. \$\endgroup\$ – Jason C Jun 13 '15 at 22:43
  • \$\begingroup\$ I have been using GCC 4.9.2 from the toolchain-test Ubuntu repo. \$\endgroup\$ – nneonneo Jun 14 '15 at 20:57
  • \$\begingroup\$ What are default options? As far as I know, you can configure the default options of gcc at compile time. \$\endgroup\$ – FUZxxl Jun 15 '15 at 8:40
  • 2
    \$\begingroup\$ Brings back memories: from around 1975 our physics teacher ran an annual "most errors from 10 (hand) punched-cards of Fortran" competition... \$\endgroup\$ – TripeHound Jun 16 '15 at 12:52
45
\$\begingroup\$

gcc 4.5.2, Score: 8579.15 (or 14367.49 for filename "a.C", may update later)

Original file, 29 bytes, compiles clean (a.cpp):

#if 0
#include"a.cpp"
#endif

Modified file, 30 bytes:

#iff 0
#include"a.cpp"
#endif

Errors:

$ gcc -c a.cpp 2>&1 | wc -c
1286873

Score:

1286873 / (30 * 5) = 8579.15

Head and tail of error output:

a.cpp:1:2: error: invalid preprocessing directive #iff
In file included from a.cpp:2:0:
a.cpp:1:2: error: invalid preprocessing directive #iff
In file included from a.cpp:2:0,
                 from a.cpp:2:
a.cpp:1:2: error: invalid preprocessing directive #iff
In file included from a.cpp:2:0,
                 from a.cpp:2,
                 from a.cpp:2:
a.cpp:1:2: error: invalid preprocessing directive #iff
In file included from a.cpp:2:0,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2:
a.cpp:1:2: error: invalid preprocessing directive #iff
In file included from a.cpp:2:0,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2:
a.cpp:1:2: error: invalid preprocessing directive #iff
In file included from a.cpp:2:0,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2:

... And so on, backing out with second error after max include depth:

a.cpp:3:2: error: #endif without #if
In file included from a.cpp:2:0,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2:
a.cpp:3:2: error: #endif without #if
In file included from a.cpp:2:0,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2:
a.cpp:3:2: error: #endif without #if
In file included from a.cpp:2:0,
                 from a.cpp:2,
                 from a.cpp:2:
a.cpp:3:2: error: #endif without #if
In file included from a.cpp:2:0,
                 from a.cpp:2:
a.cpp:3:2: error: #endif without #if
In file included from a.cpp:2:0:
a.cpp:3:2: error: #endif without #if
a.cpp:3:2: error: #endif without #if

Note:
- If .C ends up qualifying as a valid extension then score is 1,206,869 / (28 * 3) = 14,367.49.
- If Dennis' suggested second #include is added, file name "a.cpp", score is 80,797,292,934 / (46 * 5) = 351,292,578.97

\$\endgroup\$
  • 2
    \$\begingroup\$ The question says to add a character, not to replace it. \$\endgroup\$ – Dennis Jun 13 '15 at 4:41
  • 3
    \$\begingroup\$ @Dennis Oh man. I got this. Watch this second edit. Your comment was a blessing in disguise. \$\endgroup\$ – Jason C Jun 13 '15 at 4:46
  • 1
    \$\begingroup\$ @JasonC I can't upvote this enough times. \$\endgroup\$ – isaacg Jun 13 '15 at 4:50
  • 9
    \$\begingroup\$ I think you can claim an infinite score if you add a second #include"a.cpp". \$\endgroup\$ – Dennis Jun 13 '15 at 6:00
  • 3
    \$\begingroup\$ @Dennis Whoa, nice! I'm going to leave the answer as-is since I didn't think to add a second #include on my own. As for it being infinite... if it's still running when I wake up tomorrow morning, it's infinite enough for me. Will keep you posted, ha (although, it's currently piping 5.1MB/sec to wc, so if wc is using a 32-bit counter, by my calculations something weird may happen in about 13 minutes.) \$\endgroup\$ – Jason C Jun 13 '15 at 6:13
31
\$\begingroup\$

gcc 4.9.2, score: 222,898,664 663,393,783

This is heavily based on @JasonC's answer, but he said he didn't want to take credit for this improvement.

The error output of the code below is 126,044,818,789 bytes long. The score should be much higher in theory (and tend to infinity as the number of include statements increases), but it decreases in practice by adding more include statements.

Original file (37 bytes)

/*#
#include"w.cpp"
#include"w.cpp"*/
$ gcc -c w.cpp
$

Modified file (38 bytes)

/
*#
#include"w.cpp"
#include"w.cpp"*/
$ gcc -c w.cpp
w.cpp:2:2: error: stray ‘#’ in program
 *#
  ^
In file included from w.cpp:3:0:
w.cpp:2:2: error: stray ‘#’ in program
 *#
  ^
In file included from w.cpp:3:0,
                 from w.cpp:3:
w.cpp:2:2: error: stray ‘#’ in program
 *#
  ^
In file included from w.cpp:3:0,
                 from w.cpp:3,
                 from w.cpp:3:
w.cpp:2:2: error: stray ‘#’ in program
 *#
  ^
In file included from w.cpp:3:0,
                 from w.cpp:3,
                 from w.cpp:3,
                 from w.cpp:3:
⋮
w.cpp:2:2: error: stray ‘#’ in program
 *#
  ^
w.cpp:3:0: error: #include nested too deeply
 #include"w.cpp"
 ^
w.cpp:4:0: warning: extra tokens at end of #include directive
 #include"w.cpp"*/
 ^
w.cpp:4:0: error: #include nested too deeply
w.cpp:2: confused by earlier errors, bailing out
The bug is not reproducible, so it is likely a hardware or OS problem.
\$\endgroup\$
  • 5
    \$\begingroup\$ This will not technically produce infinite output, although, with current (or foreseeable) computer technology, you won't live long enough to see it stop. Basically, GCC has an #include nesting limit of 200 levels, so your recursive #includes effectively become a 200-bit binary counter. \$\endgroup\$ – Ilmari Karonen Jun 13 '15 at 6:56
  • 3
    \$\begingroup\$ Just add more include lines to get a infinite score. The output size grows faster than the code. \$\endgroup\$ – jimmy23013 Jun 13 '15 at 7:33
  • \$\begingroup\$ It could equally have been based on one of the answers from an earlier question. \$\endgroup\$ – Peter Taylor Jun 13 '15 at 7:38
  • 2
    \$\begingroup\$ It did finish this morning, with some huge number that started with an 8, and I accidentally closed the window before copying the number, because I'm awesome. I'm running it again. \$\endgroup\$ – Jason C Jun 13 '15 at 12:32
  • 3
    \$\begingroup\$ @JasonC I ran it too and got an output of 77,877,399,160 bytes. That's a lot less infinite than I expected, so I'll run it again with a shorter filename. \$\endgroup\$ – Dennis Jun 13 '15 at 14:05
25
\$\begingroup\$

gcc, 4.9.2, Score: 22.2

Original file: 0 bytes (a.cpp)

Compiles clean:

$ gcc -c a.cpp |& wc -c
0

Modified file:

(

Errors:

$ gcc -c a.cpp |& wc -c
111

Score

111/1/5 = 22.2

\$\endgroup\$
  • 4
    \$\begingroup\$ Did you already brute-force this? I mean, is this the highest score for a 0 byte start file? \$\endgroup\$ – Thomas Weller Jun 15 '15 at 15:03
  • \$\begingroup\$ No I did not brute force this. I just tried 3 or 4 different characters. This was just a seed answer to get people interested in the contest :) \$\endgroup\$ – Mark Lakata Jun 15 '15 at 21:00
23
\$\begingroup\$

11,126.95 9,105.44 2,359.37 1,645.94 266.88 points

More preprocessor abuse! This time, we're making the standard library cry.

Without typo:

#define typedf
#include<fstream>

With typo:

#define typedef
#include<fstream>

Errors:

In file included from /usr/include/c++/4.9/iosfwd:39:0,
                 from /usr/include/c++/4.9/ios:38,
                 from /usr/include/c++/4.9/istream:38,
                 from /usr/include/c++/4.9/fstream:38,
                 from a.C:2:
/usr/include/c++/4.9/bits/stringfwd.h:62:33: error: aggregate ‘std::basic_string<char> std::string’ has incomplete type and cannot be defined
   typedef basic_string<char>    string;   
                                 ^
/usr/include/c++/4.9/bits/stringfwd.h:68:33: error: aggregate ‘std::basic_string<wchar_t> std::wstring’ has incomplete type and cannot be defined
   typedef basic_string<wchar_t> wstring;   
                                 ^
/usr/include/c++/4.9/bits/stringfwd.h:78:34: error: aggregate ‘std::basic_string<char16_t> std::u16string’ has incomplete type and cannot be defined
   typedef basic_string<char16_t> u16string; 
                                  ^
/usr/include/c++/4.9/bits/stringfwd.h:81:34: error: aggregate ‘std::basic_string<char32_t> std::u32string’ has incomplete type and cannot be defined
   typedef basic_string<char32_t> u32string; 
                                  ^
In file included from /usr/include/wchar.h:36:0,
                 from /usr/include/c++/4.9/cwchar:44,
                 from /usr/include/c++/4.9/bits/postypes.h:40,
                 from /usr/include/c++/4.9/iosfwd:40,
                 from /usr/include/c++/4.9/ios:38,
                 from /usr/include/c++/4.9/istream:38,
                 from /usr/include/c++/4.9/fstream:38,
                 from a.C:2:
/usr/include/stdio.h:48:25: error: aggregate ‘_IO_FILE FILE’ has incomplete type and cannot be defined
 typedef struct _IO_FILE FILE;
                         ^
/usr/include/stdio.h:64:25: error: aggregate ‘_IO_FILE __FILE’ has incomplete type and cannot be defined
 typedef struct _IO_FILE __FILE;
                         ^
In file included from /usr/include/c++/4.9/cwchar:44:0,
                 from /usr/include/c++/4.9/bits/postypes.h:40,
                 from /usr/include/c++/4.9/iosfwd:40,
                 from /usr/include/c++/4.9/ios:38,
                 from /usr/include/c++/4.9/istream:38,
                 from /usr/include/c++/4.9/fstream:38,
                 from a.C:2:
/usr/include/wchar.h:106:9: error: ‘__mbstate_t’ does not name a type
 typedef __mbstate_t mbstate_t;
         ^
/usr/include/wchar.h:151:38: error: ‘size_t’ is not a type
     const wchar_t *__restrict __src, size_t __n)
                                      ^
/usr/include/wchar.h:159:38: error: ‘size_t’ is not a type
     const wchar_t *__restrict __src, size_t __n)
                                      ^
/usr/include/wchar.h:166:63: error: ‘size_t’ is not a type
 extern int wcsncmp (const wchar_t *__s1, const wchar_t *__s2, size_t __n)
                                                               ^
/usr/include/wchar.h:176:4: error: ‘size_t’ is not a type
    size_t __n) __THROW;
    ^
In file included from /usr/include/wchar.h:180:0,
                 from /usr/include/c++/4.9/cwchar:44,
                 from /usr/include/c++/4.9/bits/postypes.h:40,
                 from /usr/include/c++/4.9/iosfwd:40,
                 from /usr/include/c++/4.9/ios:38,
                 from /usr/include/c++/4.9/istream:38,
                 from /usr/include/c++/4.9/fstream:38,
                 from a.C:2:
/usr/include/xlocale.h:42:9: error: ‘__locale_t’ does not name a type
 typedef __locale_t locale_t;
         ^
In file included from /usr/include/c++/4.9/cwchar:44:0,
                 from /usr/include/c++/4.9/bits/postypes.h:40,
                 from /usr/include/c++/4.9/iosfwd:40,
                 from /usr/include/c++/4.9/ios:38,
                 from /usr/include/c++/4.9/istream:38,
                 from /usr/include/c++/4.9/fstream:38,
                 from a.C:2:
/usr/include/wchar.h:183:5: error: ‘__locale_t’ is not a type
     __locale_t __loc) __THROW;
     ^
/usr/include/wchar.h:186:6: error: ‘size_t’ is not a type
      size_t __n, __locale_t __loc) __THROW;
      ^
/usr/include/wchar.h:186:18: error: ‘__locale_t’ is not a type
      size_t __n, __locale_t __loc) __THROW;
                  ^
/usr/include/wchar.h:196:8: error: ‘size_t’ does not name a type
 extern size_t wcsxfrm (wchar_t *__restrict __s1,
        ^
/usr/include/wchar.h:207:9: error: ‘__locale_t’ is not a type
         __locale_t __loc) __THROW;
         ^
/usr/include/wchar.h:212:8: error: ‘size_t’ does not name a type
 extern size_t wcsxfrm_l (wchar_t *__s1, const wchar_t *__s2,
        ^
/usr/include/wchar.h:252:8: error: ‘size_t’ does not name a type
 extern size_t wcscspn (const wchar_t *__wcs, const wchar_t *__reject)
        ^
/usr/include/wchar.h:256:8: error: ‘size_t’ does not name a type
 extern size_t wcsspn (const wchar_t *__wcs, const wchar_t *__accept)
        ^
/usr/include/wchar.h:287:8: error: ‘size_t’ does not name a type
 extern size_t wcslen (const wchar_t *__s) __THROW __attribute_pure__;
        ^
/usr/include/wchar.h:306:8: error: ‘size_t’ does not name a type
 extern size_t wcsnlen (const wchar_t *__s, size_t __maxlen)
        ^

[SNIP]

/usr/include/c++/4.9/bits/fstream.tcc:934:35: error: ‘cur’ is not a member of ‘std::ios_base’
    __testvalid = this->seekoff(0, ios_base::cur, _M_mode)
                                   ^
/usr/include/c++/4.9/bits/fstream.tcc:934:50: error: ‘_M_mode’ was not declared in this scope
    __testvalid = this->seekoff(0, ios_base::cur, _M_mode)
                                                  ^
/usr/include/c++/4.9/bits/fstream.tcc:941:25: error: ‘_M_state_last’ was not declared in this scope
    + _M_codecvt->length(_M_state_last, _M_ext_buf,
                         ^
/usr/include/c++/4.9/bits/fstream.tcc:944:15: error: ‘streamsize’ does not name a type
         const streamsize __remainder = _M_ext_end - _M_ext_next;
               ^
/usr/include/c++/4.9/bits/fstream.tcc:945:13: error: ‘__remainder’ was not declared in this scope
         if (__remainder)
             ^
/usr/include/c++/4.9/bits/fstream.tcc:949:35: error: ‘__remainder’ was not declared in this scope
         _M_ext_end = _M_ext_buf + __remainder;
                                   ^
/usr/include/c++/4.9/bits/fstream.tcc:951:25: error: ‘_M_state_cur’ was not declared in this scope
         _M_state_last = _M_state_cur = _M_state_beg;
                         ^
/usr/include/c++/4.9/bits/fstream.tcc:951:40: error: ‘_M_state_beg’ was not declared in this scope
         _M_state_last = _M_state_cur = _M_state_beg;
                                        ^
/usr/include/c++/4.9/bits/fstream.tcc:960:2: error: ‘_M_codecvt’ was not declared in this scope
  _M_codecvt = _M_codecvt_tmp;
  ^
/usr/include/c++/4.9/bits/fstream.tcc:960:15: error: ‘_M_codecvt_tmp’ was not declared in this scope
  _M_codecvt = _M_codecvt_tmp;
               ^
/usr/include/c++/4.9/bits/fstream.tcc:962:2: error: ‘_M_codecvt’ was not declared in this scope
  _M_codecvt = 0;
  ^

On my Ubuntu machine, g++-4.9 -std=c++11 -c a.C generates 1,101,568 glorious bytes of errors, for a score of 1101568/33/3 = 11,126.95.

\$\endgroup\$
  • 7
    \$\begingroup\$ You should write a program to analyze all the std headers and determine which #define gives you the most points. \$\endgroup\$ – Jason C Jun 13 '15 at 18:03
  • 1
    \$\begingroup\$ You can worsen it further by replacing typedef by t;. Now you not only break every use of typedef but you get a ton of "t does not name a type" errors as well. Or %; to produce "expected unqualified-id before % token". \$\endgroup\$ – MSalters Jun 16 '15 at 10:51
  • 1
    \$\begingroup\$ #define typename * and #define int class std seemed to generate much more errors. \$\endgroup\$ – jimmy23013 Jun 16 '15 at 12:06
11
\$\begingroup\$

62.93 points

Just some C++ meta black magic, compiled with g++-4.8 -c -std=c++11 a.cc:

#include<memory>
template<int n>class B:std::unique_ptr<B<n-1>>{};template<>class B<0>{};B<-1>x;

Ungolfed:

#include <memory>

template<int n>
class B: std::unique_ptr<B<n-1>> {};

template<>
class B<0> {};

B<-1>x;

G++ has a recursion limit of 900, so changing B<1> to B<-1> with a 31-bit range has an... interesting effect.

  • 96 bytes of code (not counting the final \n some text editors automatically add, vim doesn't).
  • 4-letter filename, a.cc
  • 24165 bytes of error message, and it's truncated. The full error message has a whopping 1235889 bytes of content. It would require the -ftemplate-backtrace-limit=0 switch. It would also mean 3185 points for me!

std::unique_ptr is just the template class that manages to emit the longest error message, found by trial and error and knowledge of the STL and cats and stuff.

\$\endgroup\$
  • 2
    \$\begingroup\$ But... how can I get rid of 6 whitespaces when I only have 3 in the code, @JasonC! \$\endgroup\$ – Stefano Sanfilippo Jun 13 '15 at 17:05
7
\$\begingroup\$

Score 7.865

Strictly speaking, the 0-byte-Answer is NOT correct, as ideone.com will refuse to compile the file without error. The same is true with the example int foo(); - it won't compile on ideone.com (I'm unable to comment because of missing reputation...)

So the smallest possible program to compile without any #includes is this:

int main(){}

If you change this to the following code, it will fail with 409 bytes of error code (after renaming prog.cpp to a.cc from the ideone.com output):

int main(){[}

409 / ( 13 * 4 ) = 7.865

Please update the question accordingly, as the examples given don't respect the given rules...

\$\endgroup\$
  • 1
    \$\begingroup\$ The whole ideone thing is all kinds of goofy. \$\endgroup\$ – Jason C Jun 16 '15 at 14:04
  • \$\begingroup\$ I agree, I tacked on ideone rule after the question was posted and the first answers given. Cat is sort of out of the bag now. \$\endgroup\$ – Mark Lakata Jun 16 '15 at 16:25
1
\$\begingroup\$

C, named as .cc

main(){constexprs a(){*(int*)0=f;}a(0)}

Error code:

.code.tio.cpp: In function ‘int main()’:
.code.tio.cpp:1:8: error: ‘constexprs’ was not declared in this scope
 main(){constexprs int a(f){*(int*)0=f;}a(0);}
        ^~~~~~~~~~
.code.tio.cpp:1:8: note: suggested alternative: ‘__cpp_constexpr’
 main(){constexprs int a(f){*(int*)0=f;}a(0);}
        ^~~~~~~~~~
        __cpp_constexpr
.code.tio.cpp:1:40: error: ‘a’ was not declared in this scope
 main(){constexprs int a(f){*(int*)0=f;}a(0);}
\$\endgroup\$
  • \$\begingroup\$ Hello again! What is the original program that does not error? (I assume it is main(){}, but I am not sure) Also, isn't this just an improvement of the answer above? While you can certainly keep this answer, if it was inspired by @StefanM's answer, you should mention that. Finally, now that you have 50 rep, you can comment anywhere. \$\endgroup\$ – NoOneIsHere Oct 24 '17 at 16:11
  • \$\begingroup\$ I think this is too close to Stefan M.'s answer; I would post this as a recommended improvement for that solution. That being said, duplicate answers are allowed. Please do put the original here though and mention any inspirations (though it is possible you came up with this independently, as well) \$\endgroup\$ – HyperNeutrino Oct 24 '17 at 20:22
1
\$\begingroup\$

Score 12.xx (error by DELETING a character)

Please forgive the breaking of Rule 2 (IMHO adding OR deleting one character would be in the spirit of the rule), but this happened to me accidentally (thus doesn't use any 'intentionally' abusive tricks) while writing Real Code (TM) - both the working and error-causing code are (or look) simple and straightforward, so I thought it neat enough to include here. Original code

#include <iostream>
using namespace std;
int main ()
{
cout<<"test"<<endl;
}

Code generating the error (last '<' deleted so it looks like a less-than comparison, but noooooooooooo ...)

#include <iostream>
using namespace std;
int main ()
{
cout<<"test"<endl;
}

It's 'only' 8241 bytes of compiler error messages in ideone.com g++ 4.3.2.

\$\endgroup\$
  • 1
    \$\begingroup\$ Even if it seems to be in the spirit of the challenge (since the title says "one character typo"), this doesn't follow rule 2 which says that you can only add a character, not delete or change. \$\endgroup\$ – Jo King Sep 12 at 5:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.