我在while循环的比较器行上显示了无效读取错误。奇怪的是我检查了底部循环比较器中使用的变量,它们在那里很好,但是当while循环在顶部比较它们时它们无效地读取。它们必须发生在循环底部和顶部之间,但我不知道是什么。
这是包含故障循环的函数:
void keyMatch(Block * Buff, Key key, int * buff_fill, int * Buff_size){
int k = 0;
printf("k:%i buff fill:%i, then %i\n",k,*buff_fill,(k)<(*buff_fill));fflush(stdout);
while((k)<(*buff_fill)){
if(block_addable(key,Buff[k])){
bufadd(Buff,key,k,buff_fill,Buff_size);
}
k++;
printf("k:%i ",k);fflush(stdout);
printf("buff fill:%i",*buff_fill);fflush(stdout);
printf("then %i\n",(k)<(*buff_fill));fflush(stdout);
}
printf("done\n");fflush(stdout);
}
这是增加* buff_fill的函数:
void bufadd(Block * Buff , Key key,int buff_index, int * buff_fill, int * Buff_size){
if(*buff_fill==(*Buff_size)){
Buff = (Block*) realloc(Buff,2*(*Buff_size)*sizeof(Block));
(*Buff_size) =(*Buff_size)*2;
}
Buff[*buff_fill]=Buff[buff_index];
Buff[*buff_fill].Keys[Buff[*buff_fill].fill]=key;
Buff[*buff_fill].fill++;
(*buff_fill)=(*buff_fill)+1;
}
这是Valgrind内存检查器的一段显示无效读取:
k: 0 buff fill: 26, then 1
k: 1 buff fill: 27 then 1
k: 2 buff fill: 28 then 1
k: 3 buff fill: 29 then 1 ==
3845 == Invalid read of size 8 ==
3845 == at 0x4013B0: keyMatch(main.c: 225) ==
3845 == by 0x40167D: getBlocks(main.c: 260) ==
3845 == by 0x400A1B: main(main.c: 362) ==
3845 == Address 0x83d6130 is 240 bytes inside a block of size 2, 240 free 'd ==
3845 == at 0x4C2DEAE: realloc( in /usr/lib / valgrind / vgpreload_memcheck - amd64 - linux.so) ==
3845 == by 0x4012BF: bufadd(main.c: 198) ==
3845 == by 0x401452: keyMatch(main.c: 227) ==
3845 == by 0x40167D: getBlocks(main.c: 260) ==
3845 == by 0x400A1B: main(main.c: 362) ==
3845 ==
以下是c代码的其余部分,但我不相信它与此问题相关:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
//#include <omp.h>
#include <math.h>
double dia = 0.000001;
typedef struct {
long ID;
float value;
}Key;
Key ** Keys;
typedef struct {
int fill;
long signature;
Key Keys[4];
}Block;
typedef struct{
long signture;
Block * Blocks;
}Group;
//Function used as a tool in getExpectedBlocks to help determine the maximum possible ammount of block
unsigned long long nChoosek( unsigned n, unsigned k ){
if (k > n) return 0;
if (k * 2 > n) k = n-k;
if (k == 0) return 1;
unsigned long long result = n;
for( int i = 2; i <= k; ++i ) {
result *= (n-i+1);
result /= i;
}
return result;
}
//Finds the most probable ammount of Blocks in the database, value is used for memory allocation
int getExpectedBlocks(int rows){
double largest = 0;
for(int i =1 ; i < 4 ; i++){
double size = nChoosek(rows,i+1);
for (int j = 0 ; j < i ; j++){
size *= (2*dia);
}
if(size>largest){
largest=size;
}
}
return largest;
}
//Gets the dimensions of the database and obviously the keys as well, mainly used for memopry allocation
int * getDimensions(){
int * dimensions = (int*) calloc(2, sizeof(int));
dimensions[0]=0;
dimensions[1]=0;
FILE *fp;
if ((fp = fopen("data.txt","r")) != NULL)
{
int rows=0;
int numbers=0;
char c;
while((c=fgetc(fp))!=EOF){
if(c=='\n'){
rows++;
}
if((c=='\n')||(c==',')){
numbers++;
}
}
dimensions[0]=rows;
dimensions[1]=numbers/rows;
}
else{
printf("data.txt failed to open");
exit(1);
}
fclose(fp);
return dimensions;
}
//Get an array of doubles containing all the rowIDs
long * getIDs(int rows){
FILE *fp;
long *rowIDs;
if ((fp = fopen("keys.txt","r")) != NULL)
{
//Allocate memory for all the rowIDs
rowIDs = (long*) calloc(rows, sizeof(long));
//Fill rowIDs with the actual IDs
char c;
int ID_pos = 0;
int rowIDs_index = 0;
char ID[15]="";
//char * p;
while((c=fgetc(fp))!=EOF){
if(isdigit(c)){
ID[ID_pos]=c;
ID_pos++;
}
if(ID_pos==14){
rowIDs[rowIDs_index]=atol(ID);
rowIDs_index++;
strcpy(ID,"00000000000000");
ID_pos=0;
}
}
}
else{
printf("keys.txt failed to open");
exit(1);
}
fclose(fp);
return rowIDs;
}
//Get a 2D array of floats containing all keys in their respective columns
float ** getValues(int rows, int columns){
FILE *fp;
float **Values;
if ((fp = fopen("data.txt","r")) != NULL)
{
//Allocate memory for all the Values
Values = (float**)calloc(columns, sizeof(float*));
for(int i = 0; i < columns; i++) {
Values[i] = (float*)calloc(rows, sizeof(float));
}
//Fill Values with the actual Values
char c;
int value_pos = 0;
int row_index = 0;
int column_index = 0;
char value[9]="";
char * p;
while((c=fgetc(fp))!=EOF){
if((isdigit(c))||(c=='.')){
value[value_pos]=c;
value_pos++;
}
if(!((isdigit(c))||(c=='.'))&&(c!=13)){
Values[column_index][row_index]=strtof(value,&p);
column_index++;
strcpy(value,"00000000");
value_pos=0;
}
if(c=='\n'){
column_index=0;
row_index++;
}
}
}
else{
printf("data.txt failed to open");
exit(1);
}
fclose(fp);
return Values;
}
Key ** makeDatabase(long * rowIDs, float ** Values, int rows, int columns){
Key ** Keys = (Key**)calloc(columns, sizeof(Key*));
for(int i = 0; i < columns; i++) {
Keys[i] = (Key*)calloc(rows, sizeof(Key));
}
for(int col = 0 ; col < columns ; col++){
for(int row = 0 ; row < rows ; row++){
Keys[col][row].ID= rowIDs[row];
Keys[col][row].value=Values[col][row];
}
}
return Keys;
}
void bufadd(Block * Buff , Key key,int buff_index, int * buff_fill, int * Buff_size){
if(*buff_fill==(*Buff_size)){
Buff = (Block*) realloc(Buff,2*(*Buff_size)*sizeof(Block));
(*Buff_size) =(*Buff_size)*2;
}
Buff[*buff_fill]=Buff[buff_index];
Buff[*buff_fill].Keys[Buff[*buff_fill].fill]=key;
Buff[*buff_fill].fill++;
(*buff_fill)=(*buff_fill)+1;
}
int block_addable(Key addkey, Block block){
if(block.fill>3){
return 0;
}
for(int i = 0 ; i < block.fill ; i++){
if(block.Keys[i].ID==addkey.ID){
return 0;
}
}
return 1;
}
void keyMatch(Block * Buff, Key key, int * buff_fill, int * Buff_size){
int k = 0;
printf("k:%i buff fill:%i, then %i\n",k,*buff_fill,(k)<(*buff_fill));fflush(stdout);
while((k)<(*buff_fill)){
if(block_addable(key,Buff[k])){
bufadd(Buff,key,k,buff_fill,Buff_size);
}
k++;
printf("k:%i ",k);fflush(stdout);
printf("buff fill:%i",*buff_fill);fflush(stdout);
printf("then %i\n",(k)<(*buff_fill));fflush(stdout);
}
printf("done\n");fflush(stdout);
}
Block * getBlocks(Key * column, int ExpectedBlocks, int rows, int * blocks){
Block * Blocks = (Block*)calloc(ExpectedBlocks, sizeof(Block));
int Blocks_size = ExpectedBlocks;
//Buff = realloc(Buff,ExpectedBlocks*sizeof(Block));
int Buff_size = ExpectedBlocks;
int * buff_fill = malloc(sizeof(int));
*buff_fill=0;
for(int i = 0; i < rows ; i++){
Block * Buff = (Block*)calloc(ExpectedBlocks, sizeof(Block));
//add the 'self' block to the possible blocks buff
Buff[0].Keys[0]=column[i];
Buff[0].fill=1;
*buff_fill=1;
//check if the next key is in neighborhood
int j = i+1;
while((j<rows)&&((fabsf(column[i].value-column[j].value))<dia)){
//add match to possible blocks buffer
keyMatch(Buff,column[j],buff_fill,&Buff_size);
j++;
}
for(int j = 0; j < *buff_fill ; j++){
// printf("%i Buff No. %i ",i,j);
for(int x = 0 ; x < Buff[j].fill ; x++){
// printf("%f ",Buff[j].Keys[x].value);
}
// printf("\n");
}
//clear buffer whilst extracting full blocks
for(int j = 0 ; j <*buff_fill ; j++){
//add full blocks to blocks
if(Buff[j].fill==4){
//check if Block is large enough for the values being added and expands if neccessary
if(*blocks==(Blocks_size)){
//printf("block realloc during %i in... %i/%i..",i,*blocks,Blocks_size);fflush(stdout);
Blocks =(Block*) realloc(Blocks,2*Blocks_size*sizeof(Block));
//printf("out\n");fflush(stdout);
Blocks_size=2*Blocks_size;
}
//printf("block adding during %i in... %i/%i..",i,*blocks,Blocks_size);fflush(stdout);
Blocks[*blocks]=Buff[j];
(*blocks)=(*blocks)+1;
//printf("out\n");fflush(stdout);
}
//Buff[j].fill=0;
}
//printf("begi in %i ...",i);fflush(stdout);
free(Buff);
//rintf("done\n");fflush(stdout);
}
return Blocks;
}
int cmpkeys(const void *a, const void *b){
const Key* ka = (Key*)a;
const Key* kb = (Key*)b;
return (ka->value > kb->value) - (ka->value < kb->value);
}
void setsignatures(Block * Blocks,int blocks){
for(int i = 0 ; i < blocks ; i++){
long sig = 0;
for(int j = 0 ; j <4 ; j++){
sig += Blocks[i].Keys[j].ID;
}
Blocks[i].signature=sig;
}
}
Group * getGroups(Block ** AllBlocks){
Group * Groups;
return Groups;
}
int main(){
float fudgefactor = 1.5;
//Determine how many dimensions for preallocation of memory
int * dimensions = getDimensions();
int rows = dimensions[0];
int columns = dimensions[1];
//Load the RowIDs into an Array
long * rowIDs = getIDs(rows);
//Load the Keys into an Array
float ** Values =getValues(rows,columns);
//Generate database of all Keys
Keys = makeDatabase(rowIDs,Values,rows,columns);
//printf("first value is %f",Keys[0][0].value);
free(Values);
free(rowIDs);
Block ** AllBlocks = (Block**)calloc(columns, sizeof(Key*));
//Determine Expected number of blocks per column for predictable memory allocation
int ExpectedBlocks = fudgefactor*getExpectedBlocks(rows);
//this array stores the number of blocks in each column
int * blocks = (int*)calloc(columns, sizeof(int));
//IN parallel, organise then find the blocks in the columns
int i;
//#pragma omp parallel for
for(i=0 ; i < columns; i++){
qsort(Keys[i],rows,sizeof(Key),cmpkeys);
}
//#pragma omp parallel for
for(i=0 ; i < columns; i++){
//Sort Keys by values Database for easier search pattern
//Search for and list blocks in Keys[i]
printf("column:%i\n",i);
int blocks=0;
Block * Blocks = getBlocks(Keys[i],ExpectedBlocks,rows,&blocks);
setsignatures(Blocks,blocks);
AllBlocks[i]= Blocks;
for(int j = 0; j < blocks ; j++){
printf("%i Blocks No. %i ",i,j);
for(int x = 0 ; x < 4 ; x++){
printf("%f ",Blocks[j].Keys[x].value);
}
printf("\n");
}
}
//Put all Blocks in Groups
//Group * Groups = getGroups(AllBlocks);
return 0;
}