未为C中的字符串数组分配要释放的指针

未为C中的字符串数组分配要释放的指针,c,pointers,memory-management,free,dynamic-memory-allocation,C,Pointers,Memory Management,Free,Dynamic Memory Allocation,我知道这个问题在其他地方也存在,比如: 但是,我还是很困惑。错误似乎与“修改malloc返回的原始指针”和“在释放之前未能执行malloc”等相关。我只是不明白这些理由如何适用于我的计划 我正在编写一个动态分配的字符串数组: #include <stdio.h> #include <stdlib.h> #define NLETTERS 25 typedef struct { char** array; size_t used; size_t

我知道这个问题在其他地方也存在,比如:

但是,我还是很困惑。错误似乎与“修改malloc返回的原始指针”和“在释放之前未能执行malloc”等相关。我只是不明白这些理由如何适用于我的计划

我正在编写一个动态分配的字符串数组:

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

#define NLETTERS 25

typedef struct {
    char** array;
    size_t used;
    size_t size;
} array_t;

array_t* initArray(size_t initialSize) {
    array_t* a = malloc(sizeof(array_t));
    a->array = malloc(initialSize*sizeof(char*));
    a->used = 0;
    a->size = initialSize;

    int i;
    for(i = 0; i < initialSize; i++) {
        a->array[i] = malloc(sizeof(char) * NLETTERS);
    }

    return a;
}

void insertArray(array_t *a, char* element) {
    if (a->used == a->size) {
        a->size *= 2;

        a->array = realloc(a->array, a->size * sizeof(char*));

        int i;
        for(i = (int)a->used; i < a->size; i++) {
            a->array[i] = malloc(sizeof(char) * NLETTERS);
        }
    }
    a->array[a->used++] = element;
}

void freeArray(array_t *a) {
    int i;
    for(i = 0; i < a->size; i++) {
        free(a->array[i]);
    }

    free(a->array);
    free(a);
    a->array = NULL;
    a->used = a->size = 0;
}

void print_array(array_t *a) {
    int i;
    for(i = 0; i < a->size; i++) {
        printf("%s\n", a->array[i]);
    }
}

int main(int argc, const char * argv[]) {
    array_t *a;
    a = initArray(2);
    insertArray(a, "hello");
    insertArray(a, "how are you");
    print_array(a);
    insertArray(a, "yup");
    insertArray(a, "you know it");
    print_array(a);

    freeArray(a);

    return 0;
}
在freeArray()中for循环的第一次迭代中


非常感谢您的帮助

在您的代码中

  a->array[a->used++] = element;
您正在通过
malloc()
覆盖分配的内存,因此,稍后将其传递给
free()
时会导致问题

相关,引用
C11
,第§7.22.3.3章,
免费
功能(重点)

free
函数使ptr指向的空间被释放,即生成 可供进一步分配。如果
ptr
是空指针,则不会发生任何操作。否则,如果 参数与内存管理系统先前返回的指针不匹配 函数,或者如果通过调用free或realloc释放了空间,则 行为未定义。

另外,在稍后的一点上,这会导致,
malloc()
分配的内存实际上没有获得
free()
-d


解决方案:您应该使用将内容复制到分配的内存中。

在代码中,通过

  a->array[a->used++] = element;
您正在通过
malloc()
覆盖分配的内存,因此,稍后将其传递给
free()
时会导致问题

相关,引用
C11
,第§7.22.3.3章,
免费
功能(重点)

free
函数使ptr指向的空间被释放,即生成 可供进一步分配。如果
ptr
是空指针,则不会发生任何操作。否则,如果 参数与内存管理系统先前返回的指针不匹配 函数,或者如果通过调用free或realloc释放了空间,则 行为未定义。

另外,在稍后的一点上,这会导致,
malloc()
分配的内存实际上没有获得
free()
-d


解决方案:您应该使用将内容复制到分配的内存中。

问题的根源是行:

a->array[a->used++] = element;
它有两个问题:

  • 它泄漏内存。
    malloc()
    返回的内存丢失

  • 它指向用于字符串文本的只读内存,当您对其调用
    free
    时会出现问题

  • 将该行替换为

    strcpy(a->array[a->used++], element);
    

    问题的根源是线路:

    a->array[a->used++] = element;
    
    它有两个问题:

  • 它泄漏内存。
    malloc()
    返回的内存丢失

  • 它指向用于字符串文本的只读内存,当您对其调用
    free
    时会出现问题

  • 将该行替换为

    strcpy(a->array[a->used++], element);
    
    我看到两个问题:

  • a->array[a->used++]=元素
    您已经分配了内存,但在不使用它的情况下,您再次将其指向其他位置,从而导致内存泄漏。因此,请将其更改为:-

    strcpy(a->array[a->used++],元素)

  • 这样更改
    FreeArray
    (您正在释放内存,而不是使用它,这将导致seg故障)

    void freeArray(数组_t*a){
    int i;
    对于(i=0;isize;i++){
    自由(a->array[i]);
    }
    自由(a->数组);
    a->array=NULL;
    a->used=a->size=0;
    免费(a);
    }
    
  • 我看到两个问题:

  • a->array[a->used++]=元素
    您已经分配了内存,但在不使用它的情况下,您再次将其指向其他位置,从而导致内存泄漏。因此,请将其更改为:-

    strcpy(a->array[a->used++],元素)

  • 这样更改
    FreeArray
    (您正在释放内存,而不是使用它,这将导致seg故障)

    void freeArray(数组_t*a){
    int i;
    对于(i=0;isize;i++){
    自由(a->array[i]);
    }
    自由(a->数组);
    a->array=NULL;
    a->used=a->size=0;
    免费(a);
    }
    

  • 你是说我的realloc不正确吗?它应该改成什么?我真的不明白该链接下的修复程序是什么。请注意,在
    insertArray()
    中,您有一个成语
    old\u ptr=realloc(old\u ptr,new\u size)。这很糟糕。如果(当!)
    realloc()
    失败,您会泄漏内存,因为
    old_ptr
    已用NULL过度写入,因此您无法再释放旧内存,即使它仍然被分配。使用
    new\u ptr=realloc(旧的\u ptr,新的\u大小);如果(new_ptr==NULL){…报告错误等..}old_ptr=new_ptr
    (通常也是
    old\u size=new\u size;
    )。你是说我的realloc不正确吗?它应该改成什么?我真的不明白该链接下的修复程序是什么。请注意,在
    insertArray()
    中,您有一个成语
    old\u ptr=realloc(old\u ptr,new\u size)。这很糟糕。如果(当!)
    realloc()
    失败,您会泄漏内存,因为
    old_ptr
    已用NULL过度写入,因此您无法再释放旧内存,即使它仍然被分配。使用
    new\u ptr=realloc(旧的\u ptr,新的\u大小);如果(new_ptr==NULL){…报告错误等..}old_ptr=new_ptr(通常也是
    旧尺寸=新尺寸;
    )。