Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I copy the contents of argv[] into a c style string?

I'm trying to write a program that takes several arguments at runtime to append text to a file.

The program produces a segmentation fault at runtime. Here is the code:

int main(int argc, char* argv[])
{
    //error checking
    if (argc < 1 || argc > 4) {
        cout << "Usage: -c(optional - clear file contents) <Filename>, message to write"    << endl;
        exit(EXIT_FAILURE);
    }

    char* filename[64];
    char* message[256];

    //set variables to command arguments depending if -c option is specificed
    if (argc == 4) {
        strcpy(*filename, argv[2]);
        strcpy(*message, argv[3]);
    } else {
        strcpy(*filename, argv[1]);
        strcpy(*message, argv[2]);
    }

    int fd; //file descriptor 

    fd = open(*filename, O_RDWR | O_CREAT, 00000); //open file if it doesn't exist    then create one
    fchmod(fd, 00000);

    return 0;
}

I am still quite a beginner and I'm having immense trouble understanding c strings. What's the difference between char* and char[] and char* []?

UPDATE:

The code still throws a segmentation fault, here is my revised code:

using std::cout;
using std::endl;

 int main(int argc, char* argv[])
 {

//error checking
if (argc < 1 || argc > 4) {
cout << "Usage: -c(optional - clear file contents) <Filename>, message to write"      << endl;
 exit(EXIT_FAILURE);
 }

char filename[64];
char message[256];

 //set variables to command arguments depending if -c option is specificed
 if (argc == 4)
{
strncpy(filename, argv[2], 64);
strncpy(message, argv[3], 256);
}
 else
 {
strncpy(filename, argv[1], 64);
strncpy(message, argv[2], 256);
 }

 int fd; //file descriptor 

 fd = open(filename, O_RDWR | O_CREAT, 00000); //open file if it doesn't exist then create one
 fchmod(fd, 00000);


 return 0;

 }
like image 988
Scholar Avatar asked Dec 08 '22 12:12

Scholar


1 Answers

char* filename[64] creates an array of 64 pointers. You intend to create space for a string with 64 characters - this would be char filename[64]. Because you only allocated space for pointers, and never made the pointers point to any memory, you get a seg fault.

Solution: use char filename[64];

This creates a block of 64 bytes for your string; the value filename points to the start of this block and can be used in a copy operation

strcpy(filename, argv[2]);

I would strongly recommend using the "copy no more than n characters" function - this prevents a really long argument from causing buffer overflow. Thus

strncpy(filename, argv[2], 64);

would be safer. Even better

strncpy(filename, argv[2], 63);
filename[63] = '\0';

This guarantees that the copied string is null terminated.

You have the same problem with message. I don't think you need the code repeating...

Let me know if you need more info.

UPDATE
Today I learnt about the existence of strlcpy - see this answer. It will take care of including the NUL string terminator even when the original string was longer than the allocated space. See this for a more complete discussion, including the reasons why this function is not available on all compilers (which is of course a major drawback if you are trying to write portable code).

like image 63
Floris Avatar answered Dec 11 '22 01:12

Floris