简体   繁体   中英

malloc/struct pointer array seg fault

I have this code below, includes and other functions which are called in main are correct. But when I am trying to malloc the words[counter]->input_str , I get a segmentation fault all the time. I don't know what to do.

    struct copy {
        char *input_str;
        char *create_word;
    };

    int main(int argc, char *argv[]) {
        static struct copy *words[ARRAY_SIZE];
        char format_str[20];
        char word_str[STR_SIZE];
        int how_many;
        int counter = 0;
        char answer;

        do{

            sprintf(format_str," %%%ds",STR_SIZE - 1);
            printf("Enter string: ");
            scanf(format_str,word_str);


            words[counter]->input_str = (char *)malloc((strlen(word_str) + 1)*sizeof(char));
            if(words[counter]->input_str == NULL) {
                printf("memory problem\n");
                exit(-1);
            }
            words[counter]->input_str = word_str;

            printf("Enter integer: ");
            scanf(" %d",&how_many);

            words[counter]->create_word = duplicate(word_str,how_many);
            counter++;
            if(words[counter - 1] == NULL) {
                printf("error\n");
                exit(-1);
            }
            print(words,counter);

            do{
                printf("More (y/n)? ");
                scanf(" %c",&answer);
            }while(answer != 'y' && answer != 'n');


        }while(counter < ARRAY_SIZE && answer == 'y');

        clean(words,counter);

        return(0);
    }

Here are two versions of your code,one using struct copy *words[ARRAY_SIZE]; at the top of main() , the other using struct copy words[ARRAY_SIZE]; (which therefore does less memory allocation).

Array of pointers

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

struct copy
{
    char *input_str;
    char *create_word;
};

enum { ARRAY_SIZE = 20, STR_SIZE = 30 };

extern char *duplicate(const char *str, int number);
extern void print(struct copy **words, int number);
extern void clean(struct copy **words, int number);

int main(void)
{
    struct copy *words[ARRAY_SIZE];
    char format_str[20];
    char word_str[STR_SIZE];
    int how_many;
    int counter = 0;
    char answer;
    sprintf(format_str, " %%%ds", STR_SIZE - 1);

    do
    {
        printf("Enter string: ");
        if (scanf(format_str, word_str) != 1)
            break;

        printf("Enter integer: ");
        if (scanf(" %d", &how_many) != 1 || how_many < 0 || how_many > 999)
            break;

        words[counter] = malloc(sizeof(*words[counter]));
        words[counter]->input_str = (char *)malloc((strlen(word_str) + 1) * sizeof(char));
        if (words[counter]->input_str == NULL)
        {
            fprintf(stderr, "memory problem\n");
            exit(-1);
        }
        strcpy(words[counter]->input_str, word_str);

        words[counter]->create_word = duplicate(word_str, how_many);
        // Superfluous because duplicate exits if there is an allocation error
        if (words[counter]->create_word == NULL)
        {
            fprintf(stderr, "error\n");
            exit(-1);
        }
        counter++;
        print(words, counter);

        do
        {
            printf("More (y/n)? ");
            if (scanf(" %c", &answer) != 1)
            {
                answer = 'n';
                break;
            }
        } while (answer != 'y' && answer != 'n');
    } while (counter < ARRAY_SIZE && answer == 'y');

    clean(words, counter);

    return(0);
}

void print(struct copy **words, int number)
{
    printf("Words (%d):\n", number);
    for (int i = 0; i < number; i++)
        printf("[%s] => [%s]\n", words[i]->input_str, words[i]->create_word);
}

char *duplicate(const char *str, int number)
{
    int len1 = strlen(str);
    int len2 = number * len1 + 1;
    char *space = malloc(len2);
    if (space == NULL)
    {
        fprintf(stderr, "memory allocation failed for %d bytes\n", len2);
        exit(-1);
    }
    for (int i = 0; i < number; i++)
        strcpy(&space[i * len1], str);
    space[len2 - 1] = '\0';     // In case number == 0
    return space;
}

void clean(struct copy **words, int number)
{
    for (int i = 0; i < number; i++)
    {
        free(words[i]->input_str);
        free(words[i]->create_word);
        free(words[i]);
        words[i] = NULL;
    }
}

Array of structures

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

struct copy
{
    char *input_str;
    char *create_word;
};

enum { ARRAY_SIZE = 20, STR_SIZE = 30 };

extern char *duplicate(const char *str, int number);
extern void print(struct copy *words, int number);
extern void clean(struct copy *words, int number);

int main(void)
{
    struct copy words[ARRAY_SIZE];
    char format_str[20];
    char word_str[STR_SIZE];
    int how_many;
    int counter = 0;
    char answer;
    sprintf(format_str, " %%%ds", STR_SIZE - 1);

    do
    {
        printf("Enter string: ");
        if (scanf(format_str, word_str) != 1)
            break;

        words[counter].input_str = (char *)malloc((strlen(word_str) + 1) * sizeof(char));
        if (words[counter].input_str == NULL)
        {
            fprintf(stderr, "memory problem\n");
            exit(-1);
        }
        strcpy(words[counter].input_str, word_str);

        printf("Enter integer: ");
        if (scanf(" %d", &how_many) != 1 || how_many < 0 || how_many > 999)
            break;

        words[counter].create_word = duplicate(word_str, how_many);
        // Superfluous because duplicate exits if there is an allocation error
        if (words[counter].create_word == NULL)
        {
            fprintf(stderr, "error\n");
            exit(-1);
        }
        counter++;
        print(words, counter);

        do
        {
            printf("More (y/n)? ");
            if (scanf(" %c", &answer) != 1)
            {
                answer = 'n';
                break;
            }
        } while (answer != 'y' && answer != 'n');
    } while (counter < ARRAY_SIZE && answer == 'y');

    clean(words, counter);

    return(0);
}

void print(struct copy *words, int number)
{
    printf("Words (%d):\n", number);
    for (int i = 0; i < number; i++)
        printf("[%s] => [%s]\n", words[i].input_str, words[i].create_word);
}

char *duplicate(const char *str, int number)
{
    int len1 = strlen(str);
    int len2 = number * len1 + 1;
    char *space = malloc(len2);
    if (space == NULL)
    {
        fprintf(stderr, "memory allocation failed for %d bytes\n", len2);
        exit(-1);
    }
    for (int i = 0; i < number; i++)
        strcpy(&space[i * len1], str);
    space[len2 - 1] = '\0';     // In case number == 0
    return space;
}

void clean(struct copy *words, int number)
{
    for (int i = 0; i < number; i++)
    {
        free(words[i].input_str);
        free(words[i].create_word);
        words[i].input_str = words[i].create_word = NULL;
    }
}

Sample output:

Enter string: abc
Enter integer: 1
Words (1):
[abc] => [abc]
More (y/n)? y
Enter string: def
Enter integer: 2
Words (2):
[abc] => [abc]
[def] => [defdef]
More (y/n)? y
Enter string: absolute-twaddle
Enter integer: 10
Words (3):
[abc] => [abc]
[def] => [defdef]
[absolute-twaddle] => [absolute-twaddleabsolute-twaddleabsolute-twaddleabsolute-twaddleabsolute-twaddleabsolute-twaddleabsolute-twaddleabsolute-twaddleabsolute-twaddleabsolute-twaddle]
More (y/n)? y
Enter string: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Enter integer: 0
Words (4):
[abc] => [abc]
[def] => [defdef]
[absolute-twaddle] => [absolute-twaddleabsolute-twaddleabsolute-twaddleabsolute-twaddleabsolute-twaddleabsolute-twaddleabsolute-twaddleabsolute-twaddleabsolute-twaddleabsolute-twaddle]
[ABCDEFGHIJKLMNOPQRSTUVWXYZ] => []
More (y/n)? n

(Either program gives the same output for the same input. Both run clean under Valgrind — a site which still does not support https connections.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM