Хеш-таблица "Неинициализированное значение было создано при выделении стека"
Мы пытаемся настроить хеш-таблицу и некоторые процедуры, которые будут устанавливать, получать и удалять значения из таблицы. Мы встречаемся с проблемой "условный переход или перемещение зависит от неинициализированных значений" в строках 35 и 53.
==23720== Conditional jump or move depends on uninitialised value(s)
==23720== at 0x400CF6: hash (hashserver.c:35)
==23720== by 0x400D49: set (hashserver.c:53)
==23720== Uninitialised value was created by a stack allocation
==23720== at 0x40112A: main (hashserver.c:133)
В случае коллизии в хеш-таблице мы используем отдельную цепочку со связанным списком. Не могли бы вы помочь? Спасибо!
typedef struct KeyVal {
unsigned char* value;
unsigned char* key;
struct KeyVal* next;
}KeyVal;
unsigned long hash (unsigned char *str)
{
unsigned long hash = 5381;
int c;
(line 35) -> while (c = *str++)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash%MAXHASHTABLEN;
}
int set(KeyVal *hashtable[], unsigned char* key, unsigned char* value){
(line 53)-> unsigned long hval = hash(key);
if(hashtable[hval] == NULL){
KeyVal* runvar = calloc(1, sizeof(KeyVal));
runvar->key = key;
runvar->value = value;
runvar->next = NULL;
hashtable[hval] = runvar;
fprintf(stdout, "Successful set 1\n");
return 1;
} else {
KeyVal* counter = hashtable[hval];
KeyVal* prev = counter;
while(counter!= NULL){
prev = counter;
counter = counter->next;
}
KeyVal* runvar = calloc(1, sizeof(KeyVal));
runvar->key = key;
runvar->value = value;
runvar->next = NULL;
prev->next = runvar;
fprintf(stdout, "Successful set 2\n");
return 2;
}
return -1;
}
(line 133) -> int main(int argc, char *argv[]){
int sock, new, status, command;
struct addrinfo hints, *serverinfo, *p;
struct sockaddr_storage their_addr;
socklen_t sin_size;
int yes = 1;
char s[INET6_ADDRSTRLEN];
unsigned int numbytes = 0;
char buffer[128];
int line, transid, bitcounter = 0;
unsigned short keylenMSB, keylenLSB, keylen, vallenMSB, vallenLSB, vallen = 0;
KeyVal *hashtable[MAXHASHTABLEN];
}
Это упражнение с использованием RPC, и мы получаем команду от клиента таким образом. В самом конце мы вызываем функцию set():
unsigned char keybuf[MAXBUFFERLEN], valbuf[MAXBUFFERLEN] = {0};
while(1) {
sin_size =(socklen_t) sizeof(their_addr);
new = accept(sock, (struct sockaddr *)&their_addr, &sin_size);
if (new == -1) {
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s);
printf("server: got connection from %s\n", s);
if((numbytes = recv(new, buffer, sizeof(buffer), 0)) < 0){
perror("recv");
exit(1);
}
printf("%d\n", numbytes);
for(line = 0; line < numbytes; ++line){
printf("Byte#%d = ",line);
for(bitcounter = 0; bitcounter < 8; bitcounter++){
printf("%d ", (buffer[line] >> bitcounter)&1);
}
printf("\n");
switch(line){
case 0: switch(buffer[line]) {
case 1: command = (buffer[line]); fprintf(stdout, "line = %d, command = %d\n", line, command); /*D*/ break;
case 2: command = (buffer[line]); fprintf(stdout, "line = %d, command = %d\n", line, command); /*S*/ break;
case 3: command = (buffer[line]); fprintf(stdout, "line = %d, command = %d\n", line, command); /*SD*/ break;
case 4: command = (buffer[line]); fprintf(stdout, "line = %d, command = %d\n", line, command); /*G*/ break;
case 5: command = (buffer[line]); fprintf(stdout, "line = %d, command = %d\n", line, command); /*GD*/ break;
case 6: command = (buffer[line]); fprintf(stdout, "line = %d, command = %d\n", line, command); /*SG*/ break;
case 7: command = (buffer[line]); fprintf(stdout, "line = %d, command = %d\n", line, command); /*SGD*/ break;
default: fprintf(stdout,"Not a valid command\n"); /*Fehlermeldung*/ break;
}
case 1: transid = buffer[line]; break;
case 2: keylenMSB = buffer[line]; keylenMSB = keylenMSB << 8; break;
case 3: keylenLSB = buffer[line]; keylen = keylenMSB|keylenLSB; ; break;
case 4: vallenMSB = buffer[line]; vallenMSB = vallenMSB << 8; break;
case 5: vallenLSB = buffer[line]; vallen = vallenMSB|vallenLSB; break;
default: if(line < numbytes - vallen){
keybuf[line - 6] = buffer[line];
} else if(vallen > 0){
valbuf[line-6-keylen] = buffer[line];
}
}
}
switch(command){
case 1: delete(hashtable, keybuf); /*D*/ break;
case 2: set(hashtable, keybuf, valbuf); /*S*/ break;
case 4: get(hashtable, keybuf, valbuf); /*G*/ break;
case 3: set(hashtable, keybuf, valbuf); delete(hashtable, keybuf); /*SD*/ break;
case 6: set(hashtable, keybuf, valbuf); get(hashtable, keybuf, valbuf); /*SG*/ break;
case 5: get(hashtable, keybuf, valbuf); delete(hashtable, keybuf); /*GD*/ break;
case 7: set(hashtable, keybuf, valbuf); get(hashtable, keybuf, valbuf); delete(hashtable, keybuf); /*SGD*/ break;
default: fprintf(stdout,"Unknown command.\n")/*Fehlermeldung*/; break;
}
buffer[0] = buffer[0]|0b00001000;
send(new, buffer, sizeof(buffer), 0);
for(line = 0; line < numbytes; ++line){
printf("Sending Byte#%d = ",line);
for(bitcounter = 0; bitcounter < 8; bitcounter++){
printf("%d ", (buffer[line] >> bitcounter)&1);
1 ответ
Я вижу пару кодовых буферов в вашем коде, вы пытаетесь использовать их в качестве ключей? Например, вы можете инициализировать их так:
char s[INET6_ADDRSTRLEN] = "";
Этот код имитирует точно такое же поведение:
#include <stdio.h>
unsigned int hash(char *str) {
unsigned int hash = 5381;
int c;
while ((c = *str++))
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash % 128;
}
int main(int argc, char *argv[]) {
char initialized[20] = "hello";
printf("hash(initialized) = %u\n", hash(initialized));
char not_initialized[20];
printf("hash(not_initialized) = %u\n", hash(not_initialized));
return 0;
}