malloc / struct指针数组seg错误

时间:2018-08-19 17:32:56

标签: c struct segmentation-fault malloc

我在下面有这段代码,包括和在main中调用的其他函数是正确的。但是,当我尝试malloc words[counter]->input_str时,我总是遇到分段错误。我不知道该怎么办。

    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);
    }

1 个答案:

答案 0 :(得分:1)

这是您的代码的两个版本,一个在struct copy *words[ARRAY_SIZE];顶部使用main(),另一个使用struct copy words[ARRAY_SIZE];(因此分配的内存更少)。

指针数组

#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;
    }
}

结构数组

#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;
    }
}

示例输出:

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

(两个程序都为相同的输入提供了相同的输出。它们都在Valgrind下干净运行-这个站点仍然不支持https连接。)