简体   繁体   English

在结构内重新分配数组

[英]Reallocating array within a struct

I am writing a program for school that is asking us to create a struct which has an integer array as well as two integer variables, capacity and size, that keep track of, you guessed it, the array's size and capacity. 我正在为学校编写一个程序,要求我们创建一个结构,该结构具有一个整数数组以及两个整数变量(容量和大小),您可以猜出它的大小和容量。 The trouble is starting when I need to reallocate space for the array (the professor doesn't want us using realloc ). 当我需要为数组重新分配空间时,麻烦就开始了(教授不希望我们使用realloc )。 Here is the code... 这是代码...

dynamicArray.h file dynamicArray.h文件

#ifndef DYNAMIC_ARRAY_INCLUDED
#define DYNAMIC_ARRAY_INCLUDED 1

#ifndef __TYPE
#define __TYPE
# define TYPE int
# endif

typedef struct DynArr DynArr;

/* Dynamic Array Functions */
void initDynArr(DynArr *v, int capacity);
DynArr *newDynArr(int cap);

void freeDynArr(DynArr *v);
void deleteDynArr(DynArr *v);

int sizeDynArr(DynArr *v);

void addDynArr(DynArr *v, TYPE val);    

#endif

dynamicArray.c file dynamicArray.c文件

#include <assert.h>
#include <stdlib.h>
#include "dynArray.h"

struct DynArr
{
    TYPE *data;     /* pointer to the data array */
    int size;       /* Number of elements in the array */
    int capacity;   /* capacity ofthe array */
};

void printArray(DynArr *v)
{
    for (int i = 0; i < v->size; i++)
    {
        printf("%d, ", v->data[i]);

    }
    printf("\n");
}

void addDynArr(DynArr *v, TYPE val)
{
    /* checking that v has been initialized*/
    assert(v != 0);

    /*check if capacity is reached and increase if necessary*/
    if(v->size >= v->capacity)
    {
        _dynArrSetCapacity(v, (v->capacity) * 2);
    }

    /*add new value to array*/
    v->data[v->size] = val;

    /*increment size of array*/
    v->size++;

}

void _dynArrSetCapacity(DynArr *v, int newCap)
{
    /*check that v is initialized*/
    assert(v!=0);

    /*create temporary array with new capacity*/
    DynArr *tmp = newDynArr(newCap);

    /*copy contents of v to new array*/
    for (int i = 0; i < v->size; i++)
    {
        tmp->data[i] = v->data[i];
        tmp->size++;
    }

    /*delete contents of old array*/
    deleteDynArr(v);

    /*assign address of new array to v*/
    v = tmp;
}

void deleteDynArr(DynArr *v)
{
    freeDynArr(v);
    free(v);
}

void freeDynArr(DynArr *v)
{
    if(v->data != 0)
    {
        free(v->data);  /* free the space on the heap */
        v->data = 0;    /* make it point to null */
    }
    v->size = 0;
    v->capacity = 0;
}

DynArr *newDynArr(int cap)
{
    assert(cap > 0);
    DynArr *r = (DynArr *)malloc(sizeof( DynArr));
    assert(r != 0);
    initDynArr(r,cap);
    return r;
}

void initDynArr(DynArr *v, int capacity)
{
    assert(capacity > 0);
    assert(v!= 0);
    v->data = (TYPE *) malloc(sizeof(TYPE) * capacity);
    assert(v->data != 0);
    v->size = 0;
    v->capacity = capacity;
}

main.c file main.c文件

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

#define TYPE int

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

    DynArr *dyn;
    dyn = newDynArr(2);

    printf("\n\nTesting addDynArr...\n");
    addDynArr(dyn, 3);
    printArray(dyn);
    addDynArr(dyn, 4);
    printArray(dyn);
    addDynArr(dyn, 10);
    printArray(dyn);
    addDynArr(dyn, 5);
    printArray(dyn);
    addDynArr(dyn, 6);
    printArray(dyn);

    return 0;
}

I cut the code down (I know if probably doesn't look like it) so this is the essentials of my problem. 我削减了代码(我知道是否可能看起来不太像),所以这是我问题的要点。 I am getting a segmentation fault in the dynamicArray.c file. 我在dynamicArray.c文件中遇到分段错误。 Specifically in this function 具体在此功能

void addDynArr(DynArr *v, TYPE val)
{
    /* checking that v has been initialized*/
    assert(v != 0);

    /*check if capacity is reached and increase if necessary*/
    if(v->size >= v->capacity)
    {
        _dynArrSetCapacity(v, (v->capacity) * 2);
    }

    /*add new value to array*/
    v->data[v->size] = val;

    /*increment size of array*/
    v->size++;

}

at the v->data[v->size] = val; 在v-> data [v-> size] = val处; line. 线。 I did notice that when I check what the value of v->size is right before the previously mentioned line of code it is giving me garbage values back. 我确实注意到,当我在前面提到的代码行之前检查v-> size的值是否正确时,它给了我垃圾值。 This makes me think that when I pass v into the _dynArrSetCapacity function it is being passed by value instead of by reference but I am not seeing how that is possible. 这使我认为,当我将v传递给_dynArrSetCapacity函数时,它是通过值而不是通过引用传递的,但是我不知道如何实现。 Any help would be greatly appreciated. 任何帮助将不胜感激。

The problem is in void _dynArrSetCapacity(DynArr *v, int newCap) . 问题出在void _dynArrSetCapacity(DynArr *v, int newCap) You may want to check all of your functions that involve memory reallocation for similar problems. 您可能需要检查所有与内存重新分配有关的功能,以解决类似问题。

Technically, there are no references in C, so every parameter is passed by value, or copied. 从技术上讲,C中没有引用,因此每个参数都按值传递或复制。 But what you copied was the pointer, not the whole DynArray object. 但是复制的是指针,而不是整个DynArray对象。 Meaning when you did deleteDynArray() , the memory disappears like you'd expect, but when you get to v = tmp; 这意味着当您执行deleteDynArray() ,内存会像您期望的那样消失,但是当您到达v = tmp; , it changes the value of the local v (local copy) instead of the v that was passed in. Then when you get back to v->data[v->size] = val; ,它将更改本地v (本地副本)的值,而不是传入的v的值v->data[v->size] = val; , you're potentially accessing memory that hasn't been assigned, giving you that error. ,您可能正在访问尚未分配的内存,从而导致该错误。

The quickest fix (IMO not the best though) would be to use a double pointer instead of a single pointer for any of the functions that does deallocation like so: 最快的解决方案(IMO并不是最好的解决方案)是对执行取消分配的任何函数使用双指针而不是单指针,如下所示:

void _dynArrSetCapacity(DynArr **v, int newCap)
{
    DynArr *tmp = newDynArr(newCap);

    /*copy contents of v to new array*/
    ......
    /*delete contents of old array*/
    deleteDynArr(*v);

    /*assign address of new array to v*/
    *v = tmp;
    (*v)->size = newCap;
}

There is an alternative, and I think that might be better. 还有一种选择,我认为可能会更好。 You don't have to reallocate the whole object. 您不必重新分配整个对象。 Just the block of memory in the DynArray object holding all the relevant objects: TYPE *data DynArray对象中仅包含所有相关对象的内存块: TYPE *data

void _dynArrSetCapacity(DynArr *v, int newCap)
{
    TYPE *tmp = (TYPE*)malloc(sizeof(Type) * newCap);

    /*copy contents of v to new array*/
    for (int i = 0; i < v->size; ++i)
        tmp[i] = v->data[i];
    /*delete contents of old array*/
    free(v->data);

    /*assign address of new array to v*/
    v->data = tmp;
    v->size = newCap;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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