2011-01-06 8 views
0

この問題の説明方法が正確にわかりません。それは非常にランダムです。Cアレイの質問 - 再割り当てされたメモリでの奇妙なメモリの問題

私はここに掲載いくつかのコード持っている: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であるが)。テストコードは配列内の新しいスロットへのポインタを追加しているため、割り当てを解除してから再度実行します。

奇妙なことは、if文が明らかにそうであってはならない場合、mainの配列(array2)の2番目のテストで真と評価されるということです。

私は完全に明白な何かを見逃しているに違いない - あるいは私が気づいていないヒープ/スタックで起こっている奇妙なものがあります。

アイデア?

答えて

0

私はそれを得たと信じています。 realloc後のmemsetは、n * sizeバイトをクリアする必要があるときにnバイトだけをクリアしていました。

+0

私は行47を次のように変更しました。memset(cmpcm、0、(total - array-> total)* array-> size); – gngrwzrd

関連する問題