Home > Back-end >  why do I get "Segmentation fault" when assigning values to array of pointers
why do I get "Segmentation fault" when assigning values to array of pointers

Time:03-16

I have this peace of C Programming code to take multiple literal strings from the user and store each address to each pointer and print out the value

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char *ptr[3];
    int i = 0;

    for (; i < 3; i  ) {
        printf("ptr_%d:  ", i   1);
        fgets(ptr[i], 15, stdin);
        ptr[i][strlen(ptr[i]) - 1] = 0;
        puts(ptr[i]);
    }

    return 0;
}

However, only the first one is printed. Here is the output

ptr_1:  first line
first line
Segmentation fault

[Program finished]

I want the same result that is produced Here

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char *ptr[] = {
        "first line", 
        "second line", 
        "third line"
    };

    puts(ptr[0]);
    puts(ptr[1]);
    puts(ptr[2]);
        
    return 0;
}

output

first line
second line
third line

[Program finished]

Thanks in advance

CodePudding user response:

fgets(ptr[i], 15, stdin);

You've declared an array of three pointers:

char *ptr[3];

But none of those actually point to buffers of memory.

You can either create those buffers automatically:

char ptr[3][15];

Or dynamically with malloc.

char *ptr[3];

for (size_t i = 0; i < 3; i  ) {
    ptr[i] = malloc(15);
}

If you do this, make sure to free the memory you've allocated.

CodePudding user response:

If you are running gcc (with glibc 2.7 or greater), you can use the m modifier with scanf to allocate memory:

#include <stdio.h>
#include <string.h>

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

    for (i = 0; i < 3; i  ) {
        printf("ptr_%d:  ", i   1);
        while (scanf(" %m[^\n]",&ptr[i]) != 1)
            printf("Try again: ");
        puts(ptr[i]);
    }

    for (; i < 3; i  )
        free(ptr[i]);
    return 0;
}

And be sure to free the memory when you are done with it.

CodePudding user response:

You'd probably want to put the scanf section of this code into a function but here is the smallest change to your existing sample that should work.

$ cat allocinput.c 

#include <stdio.h>
#include <string.h>

#define MAX_LEN 80

int main(int argc, char *argv[])
{
        char c;
    char ptr[3][MAX_LEN];
    int i = 0;

for (;i<3;i  ) {
    printf("ptr_%d:  ", i   1);
    // could overflow if the user types more than MAX_LEN characters
    char *p = ptr[i];
    while (scanf("%c", &c) && (p - ptr[i] < MAX_LEN)) {
        if (c == '\n') break;
        *p   = c;
        *p = 0;
        }
    puts(ptr[i]);
}

return 0;}
$ gcc -Wall allocinput.c 
$ ./a.out
ptr_1:  first line
first line
ptr_2:  second line
second line
ptr_3:  third line
third line
$ 

P.S. I recommend astyle to clean up the formatting:

$ astyle allocinput.c 
Formatted  /tmp/overflow/allocinput.c
$ cat allocinput.c

#include <stdio.h>
#include <string.h>

#define MAX_LEN 80

int main(int argc, char *argv[])
{
    char c;
    char ptr[3][MAX_LEN];
    int i = 0;

    for (; i<3; i  ) {
        printf("ptr_%d:  ", i   1);
        // could overflow if the user types more than MAX_LEN characters
        char *p = ptr[i];
        while (scanf("%c", &c) && (p - ptr[i] < MAX_LEN)) {
            if (c == '\n') break;
            *p   = c;
            *p = 0;
        }
        puts(ptr[i]);
    }

    return 0;
}
  •  Tags:  
  • c
  • Related