C - Передача указателя в функцию, а затем передача того же указателя внутри функции в другую функцию - PullRequest
0 голосов
/ 27 июля 2011

Уф!Длинное название ... вот некоторый псевдокод для объяснения этого словоблудия:

int main(){
int* ptr = function1(); //the data that ptr points to is correct here
function2(ptr);
}

int function2(int* ptr){
//the data that ptr points to is still correct
int i;
for(i=0;i<length;printf("%d\n", (*ptr)[i]), i++); //since ptr points to a contiguous block of memory
function3(ptr);
}

int function3(int* ptr){
//the data that ptr points to is INCORRECT!!!
}

Почему данные в функции 3 будут неправильными?

Примечание: функция1 выполняет malloc () и возвращаетуказатель на эту память.

АКТУАЛЬНЫЙ КОД

#include <stdlib.h>
#include <stdio.h>

//Structures
struct hash_table_data_
{
  int key, data;
  struct hash_table_data_ *next, *prev;
};

struct hash_table_
{
  int num_entries;
  struct hash_table_data_ **entries;
};

typedef struct hash_table_data_ hash_table_data;
typedef struct hash_table_ hash_table;

//Prototypes
hash_table *new_hash_table(int num_entries);
int hash_table_add(hash_table *ht, int key, int data);
int hash_table_loader(hash_table* ht);

//Main
int main()
{
  int num_entries = 8;//THIS MUST BE AUTOMATED

  hash_table* ht = new_hash_table(num_entries);
  hash_table_loader(ht);

  return 0;
}

//Function Definitions
hash_table *new_hash_table(int num_entries)
{
  hash_table* ht = (hash_table*) malloc(sizeof(hash_table));

  hash_table_data* array = malloc(num_entries * sizeof(hash_table_data));
  int i;
  for (i=0;i<num_entries;i++)
    {
      array[i].key = -1;
      array[i].data = -1;
      array[i].next = NULL;
      array[i].prev = NULL;
    }

  ht->entries = &array;
  ht->num_entries = num_entries;

  return ht;
}

int hash_table_add(hash_table *ht, int key, int data)
{
  //VERIFY THAT THE VALUE ISN'T ALREADY IN THE TABLE!!!!!!!!!!!
  int num_entries = ht->num_entries;
  hash_table_data* array = *(ht->entries); //array elements are the LL base
  int hash_val = key%num_entries;

  printf("adding an element now...\n");
  printf("current key: %d\n", array[hash_val].key);

  int i;
  for(i=0;i<num_entries;printf("%d\n", (*(ht->entries))[i].key),i++);//DATA IS INCORRECT!!!!

  if (array[hash_val].key == -1)//is this the base link?
    {
      printf("added a new base link!\n");
      array[hash_val].key = key;
      array[hash_val].data = data;
      array[hash_val].next = NULL;
      array[hash_val].prev = &(array[hash_val]);
    }
  else//since it's not the base link...do stuff
    {
      hash_table_data* new_link = malloc(sizeof(hash_table_data));
      new_link->key = key;//set the key value
      new_link->data = data;//set the data value
      if (array[hash_val].next == NULL)//we must have the second link
    {
      printf("added a new second link!\n");
      new_link->prev = &(array[hash_val]); //set the new link's previous to be the base link
      array[hash_val].next = new_link; //set the first link's next
    }
      else//we have the 3rd or greater link
    {
      printf("added a new 3rd or greater link!\n");
      hash_table_data next_link_val = *(array[hash_val].next);
      while (next_link_val.next != NULL)//follow the links until we reach the last link
        {
          next_link_val = *(next_link_val.next);//follow the current link to the next
        }
      //now that we've reached the last link, link it to the new_link
      next_link_val.next = new_link; //link the last link to the new link
      new_link->prev = &(next_link_val); //link the new link to the last link
    }
    }

  return 0;
}

int hash_table_loader(hash_table* ht)
{
  int i;
  for(i=0;i<(ht->num_entries);printf("%d\n", (*(ht->entries))[i].key),i++); //DATA IS STILL CORRECT HERE

  FILE *infile;
  infile = fopen("input.txt", "r");
  while(!feof(infile))
    {
      int key,data;
      fscanf(infile, "%d %d", &key, &data);
      hash_table_add(ht, key, data);
    }
  fclose(infile);
}

Примечание. Проблема возникает при первом вызове hash_table_add ().

Ответы [ 3 ]

7 голосов
/ 27 июля 2011

Ваша первая проблема здесь:

ht->entries = &array;

Вы заставляете структуру хранить hash_table_data**, которая указывает на переменную hash_table_data* array, которая является локальной для функции; затем вы выходите из функции и возвращаете указатель на структуру. Структура все еще существует (она была выделена через malloc(), а материал, на который указывает array, все еще существует, но сам array нет. Соответственно, этот указатель в структуре теперь недействителен.

Насколько я могу судить, у вас нет причин держать указатель-указатель здесь. Просто используйте hash_table_data* в качестве типа записей и скопируйте array в этот член структуры. Указатели тоже являются значениями.

0 голосов
/ 27 июля 2011
hash_table *new_hash_table(int num_entries)
{
    hash_table* ht = (hash_table*) malloc(sizeof(hash_table));

    hash_table_data* array = malloc(num_entries * sizeof(hash_table_data));

    // ....

    ht->entries = &array; // Problem

    // ...
    return ht;
} // Life time of array ends at this point.

Вы берете ссылку на локальную переменную array и присваиваете ей ht->entries, которая больше не действительна после возврата из функции.

0 голосов
/ 27 июля 2011

Я полагаю, вы итерировали неправильно

for(i=0;i<length;printf("%d\n", (*ptr)[i]), i++);

это глупость.

Вы должны переписать это так:

for(i=0;i<length;i++)
    printf("%d\n", ptr[i]);

(*ptr)[i] просто неправильноэто не имеет смысла, если вы об этом думаете.

*ptr - это первый элемент массива целых чисел, на который указывают.ptr[i] это i й, это то, что вам нужно.

Пожалуйста, внимательно прочитайте Раздел 6 .

Пара советов по этому вопросу:

  1. Не пишите слишком сложный код, такой как этот оператор for с использованием оператора запятой, он просто необходим редко и приводит не только к путанице, но и к ошибкам (хотя в данном случае ошибок с этим нетпример)
  2. Внимательно следите за ошибками, не вините во всем функции.Если ваш код не работает, попробуйте найти точное место, которое не так, и докажите это.В этом примере люди, которые тестировали ваш код, были правы: функции определенно не являются причиной ошибки.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...