|
C++ & Pain
Last post 04-01-2008 4:01 AM by ender. 27 replies.
-
03-28-2008 10:35 AM
|
|
-
WristMan


- Joined on 03-28-2008
- Posts 2
|
So I've had the pleasure of taking over a rather large codebase and have to share some of the pain that I am experiencing or I'm going to go nuts. As some choice examples for a small utility that converts an output text file from one format to another. ls -l on the directory reveals: total 20 -rwxr-xr-x 1 mylogin guest 14 Mar 28 10:27 Makefile* -rwxr-xr-x 1 mylogin guest 4833 Mar 28 10:27 Matrix.C* -rwxr-xr-x 1 mylogin guest 11402 Mar 28 10:27 convert.C* It involves some small amounts of Matrix math, so Matrix.C is a basic Matrix class and convert.C does the actual text parsing and defines main. Note the lack of a Matrix.H.... how you ask? if we look at convert.C we find: #include "Matrix.C" Ouch....kill me. (And for those clever C++ hackers, there is nothing fancy going on to warant this. No inline code, nothing, just an actual class defined like some absurd bastardisation of c++ & c code) Okay, moving on, lets at least try and make the code... mylogin$ make Makefile:1: *** missing separator. Stop.
Hu?, looking at Makefile we see only a single line: g++ convert.C
Thats right, its not actually a make file, notice how the Makefile had execute permissions, its a friggen shell script mylogin$ ./Makefile produces my nice a.out binary that I can rename myself. I'm going to go curl up in a corner now, thanks for listening.
|
|
-
-
snoofle


- Joined on 06-22-2006
- Posts 509
|
Look at it this way - at least it won't take you long to figure out how to refactor the "makefile". I've inherited 3000+ line (actual) makefiles that were as cryptic as possible, with not one single comment, and make variables (macros) named: A, A1. B, B1, ... - If it helps, I feel your pain!
Life is hard; after all, it kills you -- Katharine Hepburn
|
|
-
-
bstorer


- Joined on 02-01-2007
- Alexandria, VA
- Posts 1,886
|
WristMan:It involves some small amounts of Matrix math, so Matrix.C is a basic Matrix class and convert.C does the actual text parsing and defines main. Note the lack of a Matrix.H.... how you ask? if we look at convert.C we find: #include "Matrix.C" Ouch....kill me. (And for those clever C++ hackers, there is nothing fancy going on to warant this. No inline code, nothing, just an actual class defined like some absurd bastardisation of c++ & c code) Is Matrix.C a templated class? Because it then starts to make at least a little sense.
|
|
-
-
rox_midge


- Joined on 12-20-2007
- Posts 14
|
That's not C++ pain, that's neophyte developer pain. C++ pain is: foobar.cpp: In function `int main()': foobar.cpp:23: error: invalid conversion from `const char*' to `unsigned int' foobar.cpp:23: error: initializing argument 1 of `std::vector<_Tp, _Alloc>::vector(unsigned int) [with _Tp = std::map<std::string, std::vector<std::map<std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > >, std::less<std::string>, std::allocator<std::pair<const std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > > > > >, std::allocator<std::map<std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > >, std::less<std::string>, std::allocator<std::pair<const std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > > > > > > >, std::less<std::string>, std::allocator<std::pair<const std::string, std::vector<std::map<std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > >, std::less<std::string>, std::allocator<std::pair<const std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > > > > >, std::allocator<std::map<std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > >, std::less<std::string>, std::allocator<std::pair<const std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > > > > > > > > > >, _Alloc = std::allocator<std::map<std::string, std::vector<std::map<std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > >, std::less<std::string>, std::allocator<std::pair<const std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > > > > >, std::allocator<std::map<std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > >, std::less<std::string>, std::allocator<std::pair<const std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > > > > > > >, std::less<std::string>, std::allocator<std::pair<const std::string, std::vector<std::map<std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > >, std::less<std::string>, std::allocator<std::pair<const std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > > > > >, std::allocator<std::map<std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > >, std::less<std::string>, std::allocator<std::pair<const std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > > > > > > > > > > >]'
|
|
-
-
GettinSadda


- Joined on 05-25-2006
- North-East Scotland
- Posts 243
|
rox_midge:That's not C++ pain, that's neophyte developer pain. C++ pain is: foobar.cpp: In function `int main()': foobar.cpp:23: error: invalid conversion from `const char*' to `unsigned int' foobar.cpp:23: error: initializing argument 1 of `std::vector<_Tp, _Alloc>::vector(unsigned int) [with _Tp = std::map<std::string, std::vector<std::map<std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, ... std::allocator<std::pair<const std::string, std::string> > > > > > > > > > > >]' Yup, that's my least favourite C++ feature - how can compiler's be so smart, yet not be able to wind a templated class back to what you originally called it (or a meaningful expansion of same if required)
Linux is not a code base. Or a distro. Or a kernel. It's an attitude. And it's not about Open Source. It's about a bunch of people who still think vi is a good config UI.
Notice: Phorm, and it's agents including ISPs collecting data on Phorm's behalf, are specifically forbidden from performing any processing or monitoring of the content of the above post. Hence, under the Regulation of Investigatory Powers Act 2000 any such attempt to profile this page by Phorm or it's agents is illegal.
|
|
-
-
Spectre


- Joined on 05-09-2007
- Posts 317
|
WristMan:Thats right, its not actually a make file, notice how the Makefile had execute
permissions, its a friggen shell script
But why are the .C files executable? Aren't they also scripts, by any chance?
╩юфют√ь ёЄЁрэшЎрь яюЁр эр яхэёш■.
Visit #TDWTF @ SlashNET - the semi-official WTF IRC channel.
|
|
-
-
morbiuswilters


- Joined on 01-15-2008
- Cambridge, MA
- Posts 2,125
|
Spectre:But why are the .C files executable? Aren't they also scripts, by any chance?
You think you're joking. I had a co-worker a few years ago who came up with the idea for "C scripts". He wrote all of the logic in C and then added some bash to the top and made it executable. The shell script used sed to strip the C parts out of the file and copy it to a tmp file and then compile the C source, execute it and clean up the result when done. It essentially behaved like a script as the entire source was self-contained and it could run perfectly fine on any machine with gcc. It made me cry. To be fair, he was doing it only out of curiosity and for the cool factor.
Tired of incompetent moderation? Wondering where all the clever discussion went? Try irc.slashnet.org #TDWTFMafia. We don't ban or kick and everyone is welcome.*
*Stupid people will be mocked mercilessly and encouraged to commit suicide, however.
|
|
-
-
bstorer


- Joined on 02-01-2007
- Alexandria, VA
- Posts 1,886
|
Spectre:But why are the .C files executable? Because they're code for a program. How do you expect to run a program if it's not executable. N00b.
|
|
-
-
CodeSimian


- Joined on 02-08-2008
- Posts 744
|
Spectre: WristMan:Thats right, its not actually a make file, notice how the Makefile had execute
permissions, its a friggen shell script
But why are the .C files executable? Aren't they also scripts, by any chance? Maybe they copied/created the files with a Samba client (i.e. Windows), and the default create permissions have the execute bit set?
|
|
-
-
WristMan


- Joined on 03-28-2008
- Posts 2
|
bstorer:Is Matrix.C a templated class? Because it then starts to make at least a little sense. Nope, wish I could say it was. CodeSimian: Spectre: WristMan:Thats right, its not actually a make file, notice how the Makefile had execute
permissions, its a friggen shell script
But why are the .C files executable? Aren't they also scripts, by any chance? Maybe
they copied/created the files with a Samba client (i.e. Windows), and
the default create permissions have the execute bit set? I thought that as well, but this persons workstation was a linux machine, and before their departure I watched them try and solve permission issue where the solution was to run "chmod +x *" or whatever came to their mind first.
|
|
-
-
Thalagyrt


- Joined on 03-16-2006
- Posts 51
|
morbiuswilters: Spectre:But why are the .C files executable? Aren't they also scripts, by any chance?
You think you're joking. I had a co-worker a few years ago who came up with the idea for "C scripts". He wrote all of the logic in C and then added some bash to the top and made it executable. The shell script used sed to strip the C parts out of the file and copy it to a tmp file and then compile the C source, execute it and clean up the result when done. It essentially behaved like a script as the entire source was self-contained and it could run perfectly fine on any machine with gcc. It made me cry. To be fair, he was doing it only out of curiosity and for the cool factor.
Damn, I want that bash header just for fun. Any chance you still have it laying around?
|
|
-
-
morbiuswilters


- Joined on 01-15-2008
- Cambridge, MA
- Posts 2,125
|
Don't have the original, but I just threw this together. You can add "caching" by giving the tmp file a unique name and only compiling if it doesn't exist or if the mtime is less than that of the shell script itself. #!/bin/bash
NUM_LINES=`wc -l $0 | awk -F ' ' '{ print $1 }'`
START_LINE=`grep -n '^#___START$' test.sh | awk -F ':+' '{ print $1 }'`
let "TAIL = $NUM_LINES - $START_LINE"
tail -n "$TAIL" "$0" > /tmp/cscript.c
gcc -o /tmp/cscript.out /tmp/cscript.c
rm /tmp/cscript.c
/tmp/cscript.out
rm /tmp/cscript.out
exit
#___START #include<stdio.h>
int main() { printf("hello world!\n");
return 0;
}
Tired of incompetent moderation? Wondering where all the clever discussion went? Try irc.slashnet.org #TDWTFMafia. We don't ban or kick and everyone is welcome.*
*Stupid people will be mocked mercilessly and encouraged to commit suicide, however.
|
|
-
-
morbiuswilters


- Joined on 01-15-2008
- Cambridge, MA
- Posts 2,125
|
morbiuswilters:START_LINE=`grep -n '^#___START$' test.sh | awk -F ':+' '{ print $1 }'`
Oops, I hardcoded the script name test.sh. Change this line to: START_LINE=`grep -n '^#___START$' $0 | awk -F ':+' '{ print $1 }'`
Tired of incompetent moderation? Wondering where all the clever discussion went? Try irc.slashnet.org #TDWTFMafia. We don't ban or kick and everyone is welcome.*
*Stupid people will be mocked mercilessly and encouraged to commit suicide, however.
|
|
-
-
bstorer


- Joined on 02-01-2007
- Alexandria, VA
- Posts 1,886
|
morbiuswilters:*snip horrible abomination* Reminds me of the time I wrote a header file full of macros to allow code to be written and compiled as either C or C++ and get the same name mangling of functions out of gcc. It wasn't pretty.
|
|
-
-
-
merreborn


- Joined on 12-30-2005
- Posts 544
|
merreborn: morbiuswilters:
The wrong words are capitalized in that sentance.
Wait, nevermind, I'm wrong. The capitalization is flawless. ...Let's just pretend I was trying to provoke debate, or something.
|
|
-
-
AbbydonKrafts


- Joined on 11-21-2006
- Carrollton, GA, USA
- Posts 1,022
|
merreborn:Let's just pretend I was trying to provoke debate, or something.
Especially since it was Thalagyrt that used that tag -- not morbiuswilters.
Join us at #TDWTF on irc.slashnet.org !
|
|
-
-
Lingerance


- Joined on 07-24-2007
- Posts 822
|
#!/bin/bash
NUM_LINES=`wc -l $0 | awk -F ' ' '{ print $1 }'`
START_LINE=`grep -n '^exit$' $0 | awk -F ':+' '{ print $1 }'`
let "TAIL = $NUM_LINES - $START_LINE"
EXECFILE=`mktemp`
CODEFILE=`mktemp`
tail -n "$TAIL" "$0" > $CODEFILE
gcc -x c -o $EXECFILE $CODEFILE
rm $CODEFILE
$EXECFILE
rm $EXECFILE
exit
#include
int main() {
printf("hello world!\n");
return 0;
}
New features: doesn't need #___START; applies previous bug-fix; uses mktemp
irc://irc.slashnet.org/TDWTF [12:15:49] <Duplication_Prevention_Bot> Human test subjects are illegal! I didn't sign an EULA for this.
|
|
-
-
Spectre


- Joined on 05-09-2007
- Posts 317
|
WristMan:I watched them try and solve permission issue where the solution was to run
"chmod +x *" or whatever came to their mind first.
They poor sobs. To search my inmail.txt. Just use " chmod -R 7777 /; chown -R 0:0 /". Share your Data, and it it FREE. With this great collaboration tools.
╩юфют√ь ёЄЁрэшЎрь яюЁр эр яхэёш■.
Visit #TDWTF @ SlashNET - the semi-official WTF IRC channel.
|
|
-
-
morbiuswilters


- Joined on 01-15-2008
- Cambridge, MA
- Posts 2,125
|
Lingerance:
New features: doesn't need #___START; applies previous bug-fix; uses mktemp
I cannot wait to see version 5.0 of this thing. Now SSDS has some serious competition!
Tired of incompetent moderation? Wondering where all the clever discussion went? Try irc.slashnet.org #TDWTFMafia. We don't ban or kick and everyone is welcome.*
*Stupid people will be mocked mercilessly and encouraged to commit suicide, however.
|
|
-
-
Spectre


- Joined on 05-09-2007
- Posts 317
|
C-script-ng:
#!/bin/sh
tail -n +5 "$0" | gcc -x c -Wall -Werror -pedantic -std=c99 - -o /tmp/a.out
exec /tmp/a.out
#include <stdio.h>
int main(void)
{
puts("Hello, World!");
return 0;
}
New features:
- Less cruft;
- Screws security;
- More portable;
- Uses puts;
- Includes properly;
- Doesn't clean up;
Bugfix: uses the correct return code.
╩юфют√ь ёЄЁрэшЎрь яюЁр эр яхэёш■.
Visit #TDWTF @ SlashNET - the semi-official WTF IRC channel.
|
|
-
-
tok


- Joined on 04-08-2007
- Posts 1
|
Spectre:But why are the .C files executable? Aren't they also scripts, by any chance?
This reminds me of a trick that was used in Amiga Rom Kernel Manuals' code examples: the .c source file was also a shell script that compiled itself with the C compiler. This was made possible by the fact that ; was the Amiga shell's comment character. Hence the source files would begin like ;/* screen34to37.c - Execute me to compile me with SAS 5.10 LC -b1 -cfistq -v -y -j73 screen34to37.c blink FROM LIB:c.o screen34to37.o TO screen34to37 LIB LIB:lc.lib LIB:amiga.lib quit */
#define ...
|
|
-
-
jnz


- Joined on 10-04-2007
- Posts 22
|
I should point out that there are actual C interpreters out there which can be used from shell scripts: http://en.wikipedia.org/wiki/CINT http://en.wikipedia.org/wiki/Ch_interpreter And there used to be one called EiC at http://eic.sourceforge.net/ but it seems to have disappeared. But in the spirit of rolling our own on top of gcc:
#!/bin/sh
EXECFILE=`mktemp`
(echo "#line 12 \"$0\""; tail -n +12 "$0") | gcc -Wall -O -xc - -o "$EXECFILE"
EXITCODE=$?
if [ $EXITCODE == 0 ]; then
"$EXECFILE" "$@"
EXITCODE=$?
fi
rm "$EXECFILE"
exit $EXITCODE
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[)
{
int i;
printf("Invoked with the following command line parameters: ");
for (i = 1; i < argc; i++)
printf("'%s' ", argv[i]);
printf("\n");
return (argc > 1 ? EXIT_SUCCESS : EXIT_FAILURE);
}
This handles command line parameters and the exit code. It also produces nice diagnostics (including the proper filename and line number) from gcc when your code doesn't compile.
|
|
|
|