C阵列问题 - realloc'd内存存在奇怪的内存问题

时间:2011-01-06 03:26:48

标签: c memory realloc

我不知道如何解释这个问题。这是非常随意的。

我在这里发布了一些代码:http://pastebin.com/d2vzas5S

#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>

char * s1 = "hello";

struct gdarray {
    ssize_t idx;
    size_t incr;
    size_t total;
    size_t used;
    size_t size;
    void * flex;
};
typedef struct gdarray gdarray;

gdarray * gdarray_create(size_t size, size_t incr) {
    gdarray * array = calloc(1,sizeof(gdarray));
    array->idx = -1;
    array->used = 0;
    array->total = incr;
    array->incr = incr;
    array->size = size;
    array->flex = calloc(incr,size);
    return array;
}

void gdarray_add_pntr(gdarray * array, void * pntr) {
    if(!array || !array->flex) return;
    size_t total = array->total;
    ssize_t idx = array->idx+1;
    ssize_t idx_1 = idx+1;
    void ** flex = array->flex;
    if(total < idx_1) {
        total = idx+array->incr;
        void * tmp = realloc(array->flex,array->size * total);
        if(!tmp) {
            perror("gdarray_add_pntr.!tmp");
            return;
        }
        char * cmpcm = (char *)&((char **)tmp)[idx];
        memset(cmpcm,0,(total - array->total) - 1);
        array->flex = tmp;
        array->total = total;
        flex = tmp;
    }
    if(array->used < idx_1) array->used = idx_1;
    array->idx = idx;
    if(flex[idx]) {
        printf("this should never get called!\n");
        //free(flex[idx]); - this free needs to happen ONLY if there is
        //indeed a pointer at flex[idx] - but this branch is entered
        //randomly it seems - I can't figure out why this branch is
        //entered
    }
    flex[idx] = pntr;
}

void gdarray_dealloc(gdarray * array, bool free_array,
    bool free_flex, bool free_entries)
{
    if(free_entries) {
        size_t i = 0;
        size_t c = array->used;
        void ** flex = (void **)array->flex;
        for(;i<c;i++) if(flex[i]) free(flex[i]);
    }
    if(free_flex) free(array->flex);
    if(free_array) free(array);
}

int main(int argc, char ** argv) {
    gdarray * array = gdarray_create(sizeof(char *),4);
    gdarray_add_pntr(array,strdup(s1));
    gdarray_add_pntr(array,strdup(s1));
    gdarray_add_pntr(array,strdup(s1));
    gdarray_add_pntr(array,strdup(s1));
    gdarray_add_pntr(array,strdup(s1));
    gdarray_add_pntr(array,strdup(s1));
    gdarray_add_pntr(array,strdup(s1));
    gdarray_add_pntr(array,strdup(s1));
    gdarray_dealloc(array,true,true,true);

    gdarray * array2 = gdarray_create(sizeof(char *),2);
    gdarray_add_pntr(array2,strdup(s1));
    gdarray_add_pntr(array2,strdup(s1));
    gdarray_add_pntr(array2,strdup(s1));
    gdarray_add_pntr(array2,strdup(s1));
    gdarray_dealloc(array2,true,true,true);
    return 0;
}

问题出在第54行。从技术上讲,不应该根据main()中的测试代码输入if语句。因为测试代码正在向数组中的新插槽添加指针,解除分配并再次执行。

奇怪的是,if语句在main中对数组(array2)的第二次测试的评估结果是真的,当它明显不应该是。

我必须遗漏一些完全明显的东西 - 或者我不知道堆/堆上有一些奇怪的东西。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我相信我明白了。在realloc之后我的memset只清除n个字节,当它应该清除n * size字节时。