Simple C Error

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
User avatar
lotios611
Chaos Rift Regular
Chaos Rift Regular
Posts: 160
Joined: Sun Jun 14, 2009 12:05 pm
Current Project: Game engine for the PC, PSP, and maybe more.
Favorite Gaming Platforms: Gameboy Micro
Programming Language of Choice: C++

Simple C Error

Post by lotios611 »

I am trying to code a brainfuck compiler thingy, and am almost done. However, I have ran into a problem. For some reason, the following code segfaults when ran.

Code: Select all

char* fileName = malloc((int)strlen(strcat(stripFileExtension(argv[1]), ".c")) * sizeof(char));
strcpy(fileName, strcat(stripFileExtension(argv[1]), ".c"));
...
system(strcat("gcc -std=c99 ", fileName));
"Why geeks like computers: unzip, strip, touch, finger, grep, mount, fsck, more, yes, fsck, fsck, fsck, umount, sleep." - Unknown
JesseGuarascia
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 70
Joined: Mon Dec 13, 2010 10:55 pm

Re: Simple C Error

Post by JesseGuarascia »

lotios611 wrote:I am trying to code a brainfuck compiler thingy, and am almost done. However, I have ran into a problem. For some reason, the following code segfaults when ran.

Code: Select all

char* fileName = malloc((int)strlen(strcat(stripFileExtension(argv[1]), ".c")) * sizeof(char));
strcpy(fileName, strcat(stripFileExtension(argv[1]), ".c"));
...
system(strcat("gcc -std=c99 ", fileName));
I don't really know if C and C++ differentiate in terms of their arguments. My assumption though, is that you want "argv[0]" not "argv[1]" as you're probably indexing a cell in the argv array that doesn't exist by doing the latter.
-- Jesse Guarascia

I like C/++, SDL, SFML, OpenGL and Lua. If you don't like those, then gtfo my sig pl0x (jk trollololololol)
User avatar
lotios611
Chaos Rift Regular
Chaos Rift Regular
Posts: 160
Joined: Sun Jun 14, 2009 12:05 pm
Current Project: Game engine for the PC, PSP, and maybe more.
Favorite Gaming Platforms: Gameboy Micro
Programming Language of Choice: C++

Re: Simple C Error

Post by lotios611 »

JesseGuarascia wrote:
lotios611 wrote:I am trying to code a brainfuck compiler thingy, and am almost done. However, I have ran into a problem. For some reason, the following code segfaults when ran.

Code: Select all

char* fileName = malloc((int)strlen(strcat(stripFileExtension(argv[1]), ".c")) * sizeof(char));
strcpy(fileName, strcat(stripFileExtension(argv[1]), ".c"));
...
system(strcat("gcc -std=c99 ", fileName));
I don't really know if C and C++ differentiate in terms of their arguments. My assumption though, is that you want "argv[0]" not "argv[1]" as you're probably indexing a cell in the argv array that doesn't exist by doing the latter.
The first part works AFAIK because I can use the filename before the call to system(). Also, my application requires you to at least pass in the name of the file to compile, which would be argv[1]

Edit: I check for argc !=2 before that code.
"Why geeks like computers: unzip, strip, touch, finger, grep, mount, fsck, more, yes, fsck, fsck, fsck, umount, sleep." - Unknown
User avatar
Nokurn
Chaos Rift Regular
Chaos Rift Regular
Posts: 164
Joined: Mon Jan 31, 2011 12:08 pm
Favorite Gaming Platforms: PC, SNES, Dreamcast, PS2, N64
Programming Language of Choice: Proper C++
Location: Southern California
Contact:

Re: Simple C Error

Post by Nokurn »

The problem lies in this line:

Code: Select all

system(strcat("gcc -std=c99 ", fileName));
I think you're missing some of the basic concepts of C strings, or maybe just C memory management. What's going on here is something like this: When you compile this file, the compiler will create a 14-byte space in your object file's "read-only" data section, and store the data "gcc -std=c99 \0" in it. The details of this likely change from executable format to executable format, but the idea is the same. Literal strings that are used on the fly like this, without being stored in an array of characters (whether allocated dynamically or statically, it doesn't matter), are only long enough to store the string that they are defined as when the file is compiled. You are attempting to append however many bytes to a 14-byte buffer. This is causing a buffer overflow. I'm surprised your compiler hasn't warned you about constness or something of the like--you might want to try passing "-Wall -Wextra" when you compile your code. It works wonders for pointing out such errors.

The solution, then, is to get a new buffer that *will* fit the command string. You can do this one of two ways--using a statically allocated string of some arbitrary length, or dynamically allocating it with a size that will exactly fit the string. I recommend the dynamic method, because it guarantees that all strings will fit, and that you won't have to use size-aware functions (like strncat) when dealing with the string to prevent another overflow.
Static:

Code: Select all

char cmd[64]; // Arbitrary
sprintf(cmd, "gcc -std=c99 %s", fileName);
system(cmd);
Dynamic:

Code: Select all

char *cmd = (char *)malloc(sizeof(char) * (strlen("gcc -std=c99 ") + strlen(fileName) + 1)); // The sizeof(char) may look a little redundant, but I have a habit of writing my C-style allocations to be ready to upgrade to wide characters with just a few project-wide find/replaces.
sprintf(cmd, "gcc -std=c99 %s", fileName);
system(cmd);
free(cmd);
Of course, with the dynamic approach, you're hardcoding the same literal in multiple places, so you might want to move "gcc -std=c99 " into a constant string, like so:

Code: Select all

const char compiler[] = "gcc -std=c99 ";
char *cmd = (char *)malloc(sizeof(char) * (strlen(compiler) + strlen(fileName) + 1));
sprintf(cmd, "%s%s", compiler, fileName);
system(cmd);
free(cmd);
Hope this helps.
User avatar
lotios611
Chaos Rift Regular
Chaos Rift Regular
Posts: 160
Joined: Sun Jun 14, 2009 12:05 pm
Current Project: Game engine for the PC, PSP, and maybe more.
Favorite Gaming Platforms: Gameboy Micro
Programming Language of Choice: C++

Re: Simple C Error

Post by lotios611 »

Krolgar wrote:

Code: Select all

char *cmd = (char *)malloc(sizeof(char) * (strlen("gcc -std=c99 ") + strlen(fileName) + 1)); // The sizeof(char) may look a little redundant, but I have a habit of writing my C-style allocations to be ready to upgrade to wide characters with just a few project-wide find/replaces.
sprintf(cmd, "gcc -std=c99 %s", fileName);
system(cmd);
free(cmd);
Is the +1 to account for the null character? This is my first C program by the way.
"Why geeks like computers: unzip, strip, touch, finger, grep, mount, fsck, more, yes, fsck, fsck, fsck, umount, sleep." - Unknown
User avatar
Nokurn
Chaos Rift Regular
Chaos Rift Regular
Posts: 164
Joined: Mon Jan 31, 2011 12:08 pm
Favorite Gaming Platforms: PC, SNES, Dreamcast, PS2, N64
Programming Language of Choice: Proper C++
Location: Southern California
Contact:

Re: Simple C Error

Post by Nokurn »

lotios611 wrote:
Krolgar wrote:

Code: Select all

char *cmd = (char *)malloc(sizeof(char) * (strlen("gcc -std=c99 ") + strlen(fileName) + 1)); // The sizeof(char) may look a little redundant, but I have a habit of writing my C-style allocations to be ready to upgrade to wide characters with just a few project-wide find/replaces.
sprintf(cmd, "gcc -std=c99 %s", fileName);
system(cmd);
free(cmd);
Is the +1 to account for the null character? This is my first C program by the way.
Yes. When allocating a string, you should always add one extra character for the null-terminator.
User avatar
lotios611
Chaos Rift Regular
Chaos Rift Regular
Posts: 160
Joined: Sun Jun 14, 2009 12:05 pm
Current Project: Game engine for the PC, PSP, and maybe more.
Favorite Gaming Platforms: Gameboy Micro
Programming Language of Choice: C++

Re: Simple C Error

Post by lotios611 »

Krolgar wrote:
lotios611 wrote:
Krolgar wrote:

Code: Select all

char *cmd = (char *)malloc(sizeof(char) * (strlen("gcc -std=c99 ") + strlen(fileName) + 1)); // The sizeof(char) may look a little redundant, but I have a habit of writing my C-style allocations to be ready to upgrade to wide characters with just a few project-wide find/replaces.
sprintf(cmd, "gcc -std=c99 %s", fileName);
system(cmd);
free(cmd);
Is the +1 to account for the null character? This is my first C program by the way.
Yes. When allocating a string, you should always add one extra character for the null-terminator.
Alright, thanks for the help.
"Why geeks like computers: unzip, strip, touch, finger, grep, mount, fsck, more, yes, fsck, fsck, fsck, umount, sleep." - Unknown
Post Reply