f



Dealing with 2 args

Trying something simple:

1 argument on command line: print to screen
2 arguments on command line: open file, save contents to var, print

It compiles, but with 1 argument it causes a segfault(core dump)

================================================
#include <stdio.h>
#include <string.h>
		
int main(int argc, char *argv[])
{
	char *msg = NULL;
	size_t len;
	FILE *fp;
	
   	//single arg
	if(argc==2) {
		sprintf(msg,"%s",argv[1]);
		//strcpy(msg,argv[1]);
		//tried both
	}
	
	//second arg
	//read entire file into char variable
	if(argc==3) {
		fp=fopen(argv[2],"r");
		getdelim(&msg, &len, '\0', fp);
		fclose(fp);
   	}

	//print to screen
   printf("%s\n",msg);

   return 0;
}
================================================

$./test message
Segmentation fault (core dumped)

$./test xxx filename.txt
<prints file contents>
0
DFS
12/21/2016 12:20:40 AM
comp.lang.c 30656 articles. 5 followers. spinoza1111 (3246) is leader. Post Follow

7 Replies
794 Views

Similar Articles

[PageSpeed] 33

On 21/12/16 00:20, DFS wrote:
> Trying something simple:
>
> 1 argument on command line: print to screen
> 2 arguments on command line: open file, save contents to var, print
>
> It compiles, but with 1 argument it causes a segfault(core dump)
>
> ================================================
> #include <stdio.h>
> #include <string.h>
>
> int main(int argc, char *argv[])
> {
>     char *msg = NULL;

msg points nowhere.

>     size_t len;
>     FILE *fp;
>
>       //single arg
>     if(argc==2) {
>         sprintf(msg,"%s",argv[1]);

You haven't allocated any space for msg to point to, so it still has the 
value NULL. That is your problem.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/21/2016 12:36:23 AM
On Tuesday December 20 2016 19:20, in comp.lang.c, "DFS" <nospam@dfs.com>
wrote:

> Trying something simple:
> 
> 1 argument on command line: print to screen
> 2 arguments on command line: open file, save contents to var, print
> 
> It compiles, but with 1 argument it causes a segfault(core dump)
> 
> ================================================
> #include <stdio.h>
> #include <string.h>
> 
> int main(int argc, char *argv[])
> {
> char *msg = NULL;
> size_t len;
> FILE *fp;
> 
>    //single arg
> if(argc==2) {
> sprintf(msg,"%s",argv[1]);

First off, this seems a bit of a long way around.

Why not
  msg = argv[1];
?

Secondly, 
  sprintf(msg,"%s",argv[1]);
won't work the way you think that it will work.

Think. You are telling sprintf() to format the string pointed to by
<<argv[1]>> into the character array pointed to by <<msg>>. Given that
  char *msg = NULL;
what character array does msg point to?

> //strcpy(msg,argv[1]);

  strcpy(msg,argv[1]);
won't work correctly, for the same reasons as
  sprintf(msg,"%s",argv[1]);
won't work.

> //tried both
> }
> 
> //second arg
> //read entire file into char variable
> if(argc==3) {
> fp=fopen(argv[2],"r");
> getdelim(&msg, &len, '\0', fp);

I won't comment on getdelim() other than to say that it is part of the POSIX
extensions to standard C, and not part of standard C itself.

> fclose(fp);
>    }
> 
> //print to screen
>    printf("%s\n",msg);
> 
>    return 0;
> }
> ================================================
> 
> $./test message
> Segmentation fault (core dumped)
> 
> $./test xxx filename.txt
> <prints file contents>


-- 
Lew Pitcher
"In Skills, We Trust"
PGP public key available upon request

0
Lew
12/21/2016 12:37:27 AM
On 12/20/2016 07:36 PM, Richard Heathfield wrote:
> On 21/12/16 00:20, DFS wrote:
>> Trying something simple:
>>
>> 1 argument on command line: print to screen
>> 2 arguments on command line: open file, save contents to var, print
>>
>> It compiles, but with 1 argument it causes a segfault(core dump)
>>
>> ================================================
>> #include <stdio.h>
>> #include <string.h>
>>
>> int main(int argc, char *argv[])
>> {
>>     char *msg = NULL;
>
> msg points nowhere.
>
>>     size_t len;
>>     FILE *fp;
>>
>>       //single arg
>>     if(argc==2) {
>>         sprintf(msg,"%s",argv[1]);
>
> You haven't allocated any space for msg to point to, so it still has the
> value NULL. That is your problem.


I got it working with:

msg = (char*)realloc(msg, strlen(argv[1]));


Is there a 'better' way?

Thanks Richard



0
DFS
12/21/2016 12:44:10 AM
On Tuesday December 20 2016 19:44, in comp.lang.c, "DFS" <nospam@dfs.com>
wrote:

> On 12/20/2016 07:36 PM, Richard Heathfield wrote:
>> On 21/12/16 00:20, DFS wrote:
>>> Trying something simple:
>>>
>>> 1 argument on command line: print to screen
>>> 2 arguments on command line: open file, save contents to var, print
>>>
>>> It compiles, but with 1 argument it causes a segfault(core dump)
>>>
>>> ================================================
>>> #include <stdio.h>
>>> #include <string.h>
>>>
>>> int main(int argc, char *argv[])
>>> {
>>>     char *msg = NULL;
>>
>> msg points nowhere.
>>
>>>     size_t len;
>>>     FILE *fp;
>>>
>>>       //single arg
>>>     if(argc==2) {
>>>         sprintf(msg,"%s",argv[1]);
>>
>> You haven't allocated any space for msg to point to, so it still has the
>> value NULL. That is your problem.
> 
> 
> I got it working with:
> 
> msg = (char*)realloc(msg, strlen(argv[1]));

First off, lose the cast.
Secondly, allocate the proper size
  msg = realloc(msg, strlen(argv[1])+1);

> Is there a 'better' way?

Yes, multiple 'better' ways.

1) msg = malloc(msg, strlen(argv[1])+1);
would be the expected memory allocation call. While realloc() will work with a
NULL pointer, it is usually used to /reallocate/ a given malloc()'ed space to
a new size. malloc() would be the programming idiom to /allocate/ the initial
space.

2) msg = argv[1];
<<msg>> is a pointer to char
<<argv[1]>> is a pointer to char
You don't alter the contents of the array pointed to by argv[1].
There's no need to /copy/ the string pointed to by argv[1] to something else.

-- 
Lew Pitcher
"In Skills, We Trust"
PGP public key available upon request

0
Lew
12/21/2016 12:58:20 AM
On Tuesday December 20 2016 19:58, in comp.lang.c, "Lew Pitcher"
<lew.pitcher@digitalfreehold.ca> wrote:

> On Tuesday December 20 2016 19:44, in comp.lang.c, "DFS" <nospam@dfs.com>
> wrote:
> 
>> On 12/20/2016 07:36 PM, Richard Heathfield wrote:
>>> On 21/12/16 00:20, DFS wrote:
>>>> Trying something simple:
>>>>
>>>> 1 argument on command line: print to screen
>>>> 2 arguments on command line: open file, save contents to var, print
>>>>
>>>> It compiles, but with 1 argument it causes a segfault(core dump)
>>>>
>>>> ================================================
>>>> #include <stdio.h>
>>>> #include <string.h>
>>>>
>>>> int main(int argc, char *argv[])
>>>> {
>>>>     char *msg = NULL;
>>>
>>> msg points nowhere.
>>>
>>>>     size_t len;
>>>>     FILE *fp;
>>>>
>>>>       //single arg
>>>>     if(argc==2) {
>>>>         sprintf(msg,"%s",argv[1]);
>>>
>>> You haven't allocated any space for msg to point to, so it still has the
>>> value NULL. That is your problem.
>> 
>> 
>> I got it working with:
>> 
>> msg = (char*)realloc(msg, strlen(argv[1]));
> 
> First off, lose the cast.
> Secondly, allocate the proper size
>   msg = realloc(msg, strlen(argv[1])+1);
> 
>> Is there a 'better' way?
> 
> Yes, multiple 'better' ways.
> 
> 1) msg = malloc(msg, strlen(argv[1])+1);
Cut'n'past error, sorry
      msg = malloc(strlen(argv[1])+1);
is what I should have wrote

> would be the expected memory allocation call. While realloc() will work with
> a NULL pointer, it is usually used to /reallocate/ a given malloc()'ed space
> to a new size. malloc() would be the programming idiom to /allocate/ the
> initial space.
> 
> 2) msg = argv[1];
> <<msg>> is a pointer to char
> <<argv[1]>> is a pointer to char
> You don't alter the contents of the array pointed to by argv[1].
> There's no need to /copy/ the string pointed to by argv[1] to something
> else.
> 


-- 
Lew Pitcher
"In Skills, We Trust"
PGP public key available upon request

0
Lew
12/21/2016 12:59:05 AM
On 21/12/16 00:44, DFS wrote:
> On 12/20/2016 07:36 PM, Richard Heathfield wrote:
>> On 21/12/16 00:20, DFS wrote:
>>> Trying something simple:
>>>
>>> 1 argument on command line: print to screen
>>> 2 arguments on command line: open file, save contents to var, print
>>>
>>> It compiles, but with 1 argument it causes a segfault(core dump)
>>>
>>> ================================================
>>> #include <stdio.h>
>>> #include <string.h>
>>>
>>> int main(int argc, char *argv[])
>>> {
>>>     char *msg = NULL;
>>
>> msg points nowhere.
>>
>>>     size_t len;
>>>     FILE *fp;
>>>
>>>       //single arg
>>>     if(argc==2) {
>>>         sprintf(msg,"%s",argv[1]);
>>
>> You haven't allocated any space for msg to point to, so it still has the
>> value NULL. That is your problem.
>
>
> I got it working with:
>
> msg = (char*)realloc(msg, strlen(argv[1]));
>
>
> Is there a 'better' way?

Yes. For a start, you can lose the cast, which is just typing for the 
sake of typing. Secondly, you don't have to use realloc here; malloc 
will be fine. Thirdly, you can allocate enough space to hold the string 
(at present, you're a byte short). Fourthly, you can put the allocation 
logic into a function.

char *dupstr(const char *s)
{
   char *new = NULL;
   if(s != NULL)
   {
     size_t len = strlen(s) + 1;
     new = malloc(len);
     if(new != NULL)
     {
       memcpy(new, s, len);
     }
   }
   return new;
}

and use it like this:

int main(int argc, char **argv)
{
   if(argc > 1)
   {
     char *msg = dupstr(argv[1]);
     if(msg != NULL)
     {
       printf("%s\n", msg);

       free(msg); /* give back the space when you've finished with it */
       msg = NULL; /* defensive programming */
     }
   }
   return 0;
}


-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/21/2016 1:01:25 AM
On 21/12/16 00:58, Lew Pitcher wrote:
<snip>
> You don't alter the contents of the array

string

> pointed to by argv[1].

argv[1] is a pointer to char, not a pointer to an array. We can 
reasonably say that it points to a string, however.

> There's no need to /copy/ the string pointed to by argv[1] to something else.

You're right --- he doesn't, so there isn't. But if he ever did, he 
would be wise to.

The Standard says: "The parameters argc and argv and the strings pointed 
to by the argv array shall be modifiable by the program, and retain 
their last-stored values between program startup and program termination."

That means it's okay to do this:

while(argc)
{
   printf("%s\n", argv[--argc]);
}

and it's okay to do this:

argv = NULL;

and it's even okay to do this (instead, not as well as, or at least 
certainly not after!):

assert(argc > 1);
assert(strlen(argv[1] > 6);
argv[1][6] = '!';

So far so good.

But it's less clear whether it's okay to do this:

argv[1] = "Hello world";

That is, the Standard gives us licence to change argc, and to change 
argv, and to change the strings themselves, but it doesn't give us an 
explicit licence to change the pointers argv[0] through argv[argc]. A 
cautious programmer would therefore avoid doing this, at least until 
such time as ISO clarifies the position.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/21/2016 1:13:07 AM
Reply: