ДОСТУП EXC_BAD в memcpy

Я пытаюсь построить BST и вставить в него узлы. Однако при создании нового узла я все время получаю ошибку доступа к exc_bad. Какая может быть причина? Вот мой код:

struct Node *node_create(struct BSTree *bst,void *nodeKey, struct Value *nodeVal, struct     Node *rightChild, struct Node *leftChild)
{
struct Node *node = malloc(sizeof *node);
nodeKey= malloc (sizeof (bst->key_size));
nodeVal = malloc(sizeof(bst->value_size));
size_t sizeKey = sizeof(nodeKey);
memcpy(node->key, nodeKey, sizeKey); //exc_bad access
size_t sizeVal = sizeof (nodeVal);
memcpy(node->val, nodeVal, sizeVal);//exc_bad access
node->right = rightChild;  
node->left = leftChild;

return node;

}

struct Node {
void *key;
struct Value *val;
struct Node *left;
struct Node *right;
};



struct BSTree {
size_t key_size, key_alignment;
size_t value_size, value_alignment;
int (*compare_func)(void *, void *);
struct Node *root;
// ... Maybe some other stuff.
};

struct Value {
char name[10];
int id;
};
0
nl ja de
Можете ли вы показать свои определения struct Node, BSTree и Value?
добавлено автор kamae, источник
Я добавил узел, структуры BSTree и значения
добавлено автор user1244069, источник

2 ответы

Не зная, что Node , похоже, я бы сказал, даже если вы выделили для node , вы не выделили всех членов (которые, как представляется, являются указателями ).

Измените свой код на что-то вроде:

// Allocate node
struct Node *node = malloc(sizeof *node);
// Now members
node->key = malloc (sizeof (bst->key_size)); 
// :

Если вы передаете ключ и значение, затем выполните memcpy этих значений в вышеуказанных местах. Но трудно сказать без дальнейшего кода ...

2
добавлено
это может иметь место, однако каждый Node также должен быть правильно назначен и инициализирован (т. е. вышеупомянутый подход, выделить место для узла, а затем место для соответствующих членов) ...
добавлено автор Nim, источник
когда вы выделяете node , malloc возвращает вам блок памяти размером Node . Указатели не инициализируются ничем полезным, вам нужно указать указатели на что-то, например key - это указатель, но он не указывает ни на что. Вам нужно создать пространство для хранения ключа, и как только вы это сделаете, сделайте указатель на него ... затем скопируйте соответствующие данные.
добавлено автор Nim, источник
Вы действительно не сказали, как вы звоните или используете эту функцию. Если ваше намерение заключается в том, что параметры ( nodeKey и nodeValue ) являются параметрами output ), вам необходимо изменить подпись (поиск указателя на указатель, указатель). В этом случае вы можете выделить внутри функции, как вы делаете, и вам просто нужно изменить ключ node-> , чтобы указать на то же место (не memcpy ), если вы передаете указатели на ключ и значение как параметры, то, как только вы выделили, как указано выше, в моем ответе, вызовите memcpy .
добавлено автор Nim, источник
@ user1244069: Обратите внимание, что sizeof (bst-> key_size) принимает размер размера . Вы хотите передать размер ключа, а не размер ключа. То же самое касается value_size .
добавлено автор Peter Hosey, источник
В моем bst_new поля функции BSTree инициализируются и создается дерево.
добавлено автор user1244069, источник
struct BSTree * bst_new (size_t key_sz, size_t key_algn, size_t val_sz, size_t val_algn, int (* cmp) (void * key1_vp, void * key2_vp)) {struct BSTree * bst = malloc (sizeof * bst); bst-> key_size = (key_sz + key_algn) & (~ key_algn-1); bst-> value_size = (val_sz + val_algn) & (~ val_algn-1); bst-> compare_func = cmp; bst-> root = NULL; return bst; }
добавлено автор user1244069, источник
doen't это делать это за ключ и ценность? nodeKey = malloc (sizeof (bst-> key_size)); nodeVal = malloc (sizeof (bst-> value_size));
добавлено автор user1244069, источник
Мне нужно сделать то, что вы сказали, но я точно не знаю, как это сделать
добавлено автор user1244069, источник

Не смотря на структуру узла, я бы предположил, что вы хотите сделать:

если узел определен как

struct Node {
    void *key;
    struct Value *val;
    struct Node *right;
    struct Node *left;
};

тогда

struct Node *node_create(struct BSTree *bst,void *nodeKey, struct Value *nodeVal, struct     Node *rightChild, struct Node *leftChild)
{
struct Node *node = malloc(sizeof *node);

  node->key = malloc(bst->key_size);          /* No sizeof here */
  node->val = malloc(bst->value_size);
  memcpy(node->key, nodeKey, bst->key_size);  
  memcpy(node->val, nodeVal, bst->value_size);
  node->right = rightChild;  
  node->left = leftChild;

  return node;
}

Поскольку вы не проверяете возврат malloc s (который является выбором дизайна, который может быть оправдан), вы даже можете записать его более простым способом.

struct Node *node_create(struct BSTree *bst,void *nodeKey, struct Value *nodeVal, struct     Node *rightChild, struct Node *leftChild)
{
struct Node *node = malloc(sizeof *node);

  node->key = memcpy(malloc(bst->key_size)  , nodeKey, bst->key_size); 
  node->val = memcpy(malloc(bst->value_size), nodeVal, bst->value_size);
  node->right = rightChild;  
  node->left = leftChild;
  return node;
}

Есть люди, которые съеживаются в этом стиле, но я предпочитаю не слишком разбавлять свой код избытками.

0
добавлено
Хорошо, я изменил код соответственно. Поскольку у вас уже есть размеры в bst, вы можете использовать их напрямую.
добавлено автор Patrick Schlüter, источник
Да, я хочу сделать что-то вроде первого, но мне нужно выделить память для ключа и значения с размером bst-> key_size = (key_sz + key_algn) & (~ key_algn-1) и bst-> value_size = (val_sz + val_algn) & (~ val_algn-1)
добавлено автор user1244069, источник
Спасибо. Это сработало:)
добавлено автор user1244069, источник