2

I have two c program "main.c" and "ArgHandle.c".

main.c

#include <stdio.h>
#include <stdlib.h>

main ( int argc, char * argv[] ){
    char * a[4];
    save_arg( argc, argv );

    a[0]=get_arg(); //warning: assignment makes pointer from integer without a cast
    if ( a[0] != NULL )
        printf("a[0]=%s\n", a[0] );
}

ArgHandle.c

#include <stdio.h>
#include <stdlib.h>

static char * arg[5];

void save_arg( int argc, char * argv[] ){
    int i;
    for ( i=1; i<argc; i++ ){
        arg[i-1]=argv[i];
        printf("save_arg: arg[%d]=%s\n", (i-1), arg[i-1]);
    }
}

char * get_arg(){
    printf("get_arg: arg[0]=%s\n", arg[0] );
    return (arg[0]);
}

And while I execute the program "./main -abc", it returns

save_arg: arg[0]=-abc
get_arg: arg[0]=-abc
Segmentation fault (core dumped)

It can print out the char* argument inside ArgHandle.c but not in main.c after returning from function get_arg().

I am new in c programming and have no idea why would this happens. Then I find Iharob Al Asimi's post, and think maybe I should use malloc() to reserve non-local memory for the argument. So I revise the code like this:

main.c (revised)

#include <stdio.h>
#include <stdlib.h>

main ( int argc, char * argv[] ){
    char * a[4];
    save_arg( argc, argv );
    a[0]=malloc(50); // <~~~~ new added
    a[0]=get_arg(); //warning: assignment makes pointer from integer without a cast
    if ( a[0] != NULL )
        printf("a[0]=%s\n", a[0] );
    free(a[0]); // <~~~~ new added
}

ArgHandle.c (revised)

#include <stdio.h>
#include <stdlib.h>

static char * arg[5];

void save_arg( int argc, char * argv[] ){
    int i;
    for ( i=1; i<argc; i++ ){
        arg[i-1]=malloc(50); // <~~~~ new added
        arg[i-1]=argv[i];
        printf("save_arg: arg[%d]=%s\n", (i-1), arg[i-1]);
    }
}

char * get_arg(){
    printf("get_arg: arg[0]=%s\n", arg[0] );
    return (arg[0]);
}

But, it makes no difference, the Segmentation fault still comes out.

Solved

Thanks for the suggestion from chux, Retired Ninja and Lưu Vĩnh Phúc. Problem solved by adding the declaration header.

Frankie
  • 21
  • 1
  • 4
  • The `=` operator doesn't copy strings in C. See https://stackoverflow.com/questions/9593798/proper-way-to-copy-c-strings (and many other articles online about how to copy C-strings) – Michael Albers Jun 19 '17 at 03:13
  • 5
    `main.c` needs `char * get_arg(void);` and `void save_arg(int argc, char * argv[])` declarations. – chux - Reinstate Monica Jun 19 '17 at 03:13
  • Hi, and welcome to Stack Overflow! What are you attempting to do here? Make a copy of `argv`? If so, why? – Schwern Jun 19 '17 at 03:15
  • 2
    To elaborate on what @chux said, without a prototype `c` assumes `get_arg` returns an int. – Retired Ninja Jun 19 '17 at 03:19
  • you must include `ArgHandle.h` so that main.c sees `get_arg` prototype, `arg[i-1]=malloc(50); arg[i-1]=argv[i];` introduces memory leak because the address of the allocated memory block is lost right away – phuclv Jun 19 '17 at 03:22
  • Thanks @Michael Albers. But it seems not a problem of string copying as it also cannot print directly from get_arg() returns `printf("%s\n", get_arg() );` – Frankie Jun 19 '17 at 03:52
  • @Schwern, actually it is my friend's programs. The program is not that simple, but I located the problem and simplified it here. – Frankie Jun 19 '17 at 03:54
  • Thanks chux, Retired Ninja and Lưu Vĩnh Phúc. It works after including the declaration header. Thank you. =) – Frankie Jun 19 '17 at 03:57
  • What's the point of the added call to `malloc`? You immediately overwrite the value `malloc` returns with another value, leaking the memory you allocated. – David Schwartz Jun 19 '17 at 04:19
  • You should ask a question about *the warning* rather than *the crash*. This way you won't need to *execute your programs* to see *the crash* because you'll know about *the crash* **before** you execute it! Warnings are *warnings*, after all, right? – autistic Jun 19 '17 at 04:47
  • @David Schwartz, yes you are right. I guessed the problem may relate to memory allocation, but it turns out I am totally wrong. – Frankie Jun 19 '17 at 06:05
  • @Seb, as I mentioned, the original programs are not that simple. There are many warnings, but it only stuck up on the error I point out. So I simply ignore all its warnings and strive on the error. And yes, you are right, and I should also take those warning seriously next time. – Frankie Jun 19 '17 at 06:14
  • @Frankie When it comes to warnings and errors, it's often the case that eliminating the first also eliminates subsequent warnings/errors. Thus, you should start from the top, asking questions about those you don't understand, fixing them as you learn to understand what they're saying and how to fix them... and if you start the process with 20 warnings and fix one to find them all disappear, then you had 19 warnings you didn't need to ask about... – autistic Jun 20 '17 at 07:31
  • @Seb Yes, I totally agree with you. Laziness makes mistakes. – Frankie Jun 21 '17 at 07:16

0 Answers0