使用 realloc 获取段错误

问题描述 投票:0回答:1

我正在尝试解决最近在我朋友的大学考试中出现的以下问题(现在考试已经结束并发布了论文)

开发一个 C 程序来管理歌曲的播放列表,其中每首歌曲都有一个标题和持续时间(以秒为单位)。使用两个单独的动态分配数组来存储标题和持续时间。使用指针算法实现用户定义的函数来添加、删除、更新和显示播放列表信息。 [10分]

我做了以下尝试:

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

const size_t MAX_NAME_LENGTH = 20;
size_t number_of_songs = 0;

char* names_of_songs;
int* durations;

void add(char* name_of_song, int duration) {
    number_of_songs++;

    names_of_songs = realloc(name_of_song, MAX_NAME_LENGTH * number_of_songs);
    durations = realloc(durations, number_of_songs * sizeof(int));

    int start_location = ((number_of_songs - 1) * MAX_NAME_LENGTH) + 1;
    char* name_location = &name_of_song[start_location];

    strncpy(name_location, name_of_song, MAX_NAME_LENGTH);

    names_of_songs[start_location + strlen(name_of_song) + 1] = 0;
    durations[number_of_songs - 1] = duration;
}

void display() {
    for (size_t i = 0; i < number_of_songs; i++) {
        int position_in_name = 0;
        int start_location = (i * MAX_NAME_LENGTH) + 1;
        char character = 1;

        printf("Name: ");
        while (character != 0) {
            character = names_of_songs[start_location++];
            printf("%c", character);
        }

        printf(", Duration: %d sec\n", durations[i]);
    }
}

int main(int argc, char const *argv[]) {
    names_of_songs = malloc(1);
    durations = malloc(1);

    display();
    add("Something", 2);
    display();
    add("Something else", 32);
    display();
    add("boring song", 4);
    display();

    free(names_of_songs);
    free(durations);

    return 0;
}

当我运行它时,出现分段错误。使用我的调试器,它似乎在第一次运行

realloc()
时发生,当
add()
尝试调整新歌曲标题时。发生了什么事,我该如何解决?

另外,我该如何调试这样的东西?

c memory-management dynamic-memory-allocation
1个回答
2
投票
  1. relloc()
    用于调整动态内存的大小。最简单的修复是只允许全局变量的默认 0 初始化。

  2. realloc()
    的返回值赋给一个临时值,否则如果
    realloc()
    失败,您将泄漏内存。

  3. 第一个

    realloc()
    中使用的变量不正确
    name_of_song
    当你的意思是
    names_of_songs
    .

  4. 使用符号常量而不是常量值。在堆栈上分配内存时需要前者,否则它们将成为 VLA。

  5. 起始位置的

    + 1
    错了

  6. 删除了每个

    display()
    之后的
    add()
    ,因为它让我感到困惑。

  7. (不固定)对于

    names_of_songs
    ,考虑使用字符指针数组(即
    char **names_of_songs
    ):
    names_of_songs[number_of_songs] = strndup(name_of_songs, MAX_NAME_LENGTH)
    这更容易,而且您没有浪费空间。

  8. (不固定)如果您真的想使用 char 数组,请考虑使用指向 char 数组的指针对其进行索引

    (*p)[MAX_NAME_LENGTH]
    ,以便编译器为您缩放指针。

  9. display()
    :更容易单独打印每个字符的字符串,然后您可以将所有
    printf()
    调用组合成一个。

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

#define MAX_NAME_LENGTH 20
size_t number_of_songs;
char* names_of_songs;
int* durations;

void add(char* name_of_song, int duration) {
    char *tmp = realloc(names_of_songs, MAX_NAME_LENGTH * (number_of_songs + 1));
    if(!tmp) {
        printf("malloc failed\n");
        return;
    }
    names_of_songs = tmp;
    strncpy(names_of_songs + number_of_songs * MAX_NAME_LENGTH, name_of_song, MAX_NAME_LENGTH);
    names_of_songs[number_of_songs * MAX_NAME_LENGTH + strlen(name_of_song)] = '\0';

    int *tmp2 = realloc(durations, sizeof *tmp2 * (number_of_songs + 1));
    if(!tmp2) {
        printf("malloc failed\n");
        return;
    }
    durations = tmp2;
    durations[number_of_songs] = duration;
    number_of_songs++;
}

void display() {
    for (size_t i = 0; i < number_of_songs; i++)
        printf("Name: %s, Duration %d sec\n",
            names_of_songs + i * MAX_NAME_LENGTH,
            durations[i]
        );
}

int main() {
    add("Something", 2);
    add("Something else", 32);
    add("boring song", 4);
    display();
    free(names_of_songs);
    free(durations);
}

示例输出:

Name: Something, Duration: 2 sec
Name: Something else, Duration: 32 sec
Name: boring song, Duration: 4 sec
© www.soinside.com 2019 - 2024. All rights reserved.