0

Unfortunately problem looks for me to be quite complex.

I'm having set of structs and function. Pardon me for terrible naming.

hashmap.h

#ifndef HASHMAP_H
#define HASHMAP_H

typedef struct HashMapNode HashMapNode;

struct HashMapNode {
  char *key;
  int  value;
  HashMapNode *collision;
};

typedef struct {
  int size;
  HashMapNode **map;
} HashMap;

HashMap *hashmap_new(size_t size);
HashMapNode *hashmap_node_new(HashMapNode *node);

#endif

hashmap.c

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "hashmap.h"

HashMapNode *hashmap_node_new(HashMapNode *node){
  
  node = malloc(sizeof(HashMapNode));

  node->key       = NULL;
  node->value     = 0;
  node->collision = NULL;

  return node;

};

HashMap *hashmap_new(size_t size){

  HashMap *hash_map = malloc(sizeof(HashMap));

  hash_map->size = size;
  hash_map->map  = malloc(sizeof(HashMapNode*) * size);

  HashMapNode *node;

  for (int i = 0; i < hash_map->size; i++){  
    node = hashmap_node_new(hash_map->map[i]);
    printf("Node pointer: %p, key pointer: %p, collision pointer %p\n", node, node->key, node->collision);
  };

  return hash_map;

};

Here is program workflow and error.

main.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "hashmap.h"

int main(){

  HashMap *hash_map = hashmap_new(100);
  
  printf("%p\n", hash_map->map[4]->key);

  return 0;
};

Output:

...
Node pointer: 0x5607cb89b8b0, key pointer: (nil), collision pointer (nil)
Node pointer: 0x5607cb89b8d0, key pointer: (nil), collision pointer (nil)
Node pointer: 0x5607cb89b8f0, key pointer: (nil), collision pointer (nil)
Node pointer: 0x5607cb89b910, key pointer: (nil), collision pointer (nil)
Node pointer: 0x5607cb89b930, key pointer: (nil), collision pointer (nil)
Node pointer: 0x5607cb89b950, key pointer: (nil), collision pointer (nil)
Node pointer: 0x5607cb89b970, key pointer: (nil), collision pointer (nil)
Segmentation fault (core dumped)

Program fails at:

(Important fact is that it fails to print pointer for index > 3)

Program received signal SIGSEGV, Segmentation fault.
main () at usage.c:18
18        printf("%p\n", hash_map->map[4]->key);

GDB debug:

(gdb) print hash_map
$11 = (HashMap *) 0x5555555594a0
(gdb) print hash_map->map[0]->key
$12 = 0x7ffff7fa82f0 <main_arena+1648> "\340\202\372\367\377\177"
(gdb) print hash_map->map[1]->key
$13 = 0x7ffff7fa82f0 <main_arena+1648> "\340\202\372\367\377\177"
(gdb) print hash_map->map[2]->key
$14 = 0x0
(gdb) print hash_map->map[3]->key
$15 = 0x0
(gdb) print hash_map->map[4]->key
Cannot access memory at address 0x61590a616963616d

Not really sure where am I making a mistake..

1 Answer 1

2

The function hashmap_node_new creates a new node and returns it, but it doesn't modify the original pointer that was passed in to the function by its argument.

That means that the statement

node = hashmap_node_new(hash_map->map[i]):

will not modify hash_map->map[i]. You need to assign the pointer the function returns back to hash_map->map[i]:

node = hashmap_node_new(hash_map->map[i]):
hash_map->map[i] = node;

The reason that the hashmap_node_new doesn't modify the original pointer you pass in as the argument is because arguments in C are passed by value. That means the original value is copied, and the function only works on the copy not the original.

This is basically the same as something like:

int set_int(int value)
{
    value = 5;
    return value;
}

// ...

int my_value;
int new_value;

new_value = set_int(my_value);

And expecting my_value to become initialized.

Sign up to request clarification or add additional context in comments.

4 Comments

Wow, thank you for that, although I'm not sure why pointer that's passed to a function is not changed.
I think I understand now, it took me some time :) I was sure that I can perfom operations on existing in-memory data from function itself - and it's true. But in this scenerio I'm allocating new memory and this memory pointer is assigned to node variable only within function scope. Thank you Sir!
Since there was no memory allocated to original pointer, I assume there is no need to free anything right?
@h0ax In the code as shown in the question you save the pointer to node, which you then promptly discard, leading to a memory leak. If you save the pointer it will point to memory returned by malloc and should be passed to free.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.