Проблема с передачей массива указателей для структурирования среди функций в C - PullRequest
0 голосов
/ 25 апреля 2010

Код, который следует за ошибками при вызове strncpy, и я не вижу, что я делаю неправильно. Мне нужен еще один набор глаз, чтобы посмотреть на это. По сути, я пытаюсь выделить память для структуры, на которую указывает элемент в массиве указателей на структуру.

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

#define MAX_POLICY_NAME_SIZE 64
#define POLICY_FILES_TO_BE_PROCESSED "SPFPolicyFilesReceivedOffline\0"

typedef struct TarPolicyPair
{
  int AppearanceTime;
  char *IndividualFile;
  char *FullPolicyFile;
} PolicyPair;


enum {
    bwlist = 0,
    fzacts,
    atksig,
    rules,
    MaxNumberFileTypes
  };


void SPFCreateIndividualPolicyListing(PolicyPair *IndividualPolicyPairtoCreate )
{
  IndividualPolicyPairtoCreate = (PolicyPair *) malloc(sizeof(PolicyPair));
  IndividualPolicyPairtoCreate->IndividualFile = (char *)malloc((MAX_POLICY_NAME_SIZE * sizeof(char)));
  IndividualPolicyPairtoCreate->FullPolicyFile = (char *)malloc((MAX_POLICY_NAME_SIZE * sizeof(char))); 

  IndividualPolicyPairtoCreate->AppearanceTime = 0;
  memset(IndividualPolicyPairtoCreate->IndividualFile, '\0', (MAX_POLICY_NAME_SIZE * sizeof(char)));
  memset(IndividualPolicyPairtoCreate->FullPolicyFile, '\0', (MAX_POLICY_NAME_SIZE * sizeof(char)));
}

void SPFCreateFullPolicyListing(SPFPolicyPair **CurrentPolicyPair, char *PolicyName, char *PolicyRename)
{              
  int i;

  for(i = 0; i < MaxNumberFileTypes; i++)
    {
      CreateIndividualPolicyListing((CurrentPolicyPair[i]));
      // segfaults on this call
      strncpy((*CurrentPolicyPair)[i].IndividualFile, POLICY_FILES_TO_BE_PROCESSED, (SPF_POLICY_NAME_SIZE * sizeof(char)));

    }
}

int main()
{
  SPFPolicyPair *CurrentPolicyPair[MaxNumberFileTypes] = {NULL, NULL, NULL, NULL};
  int i;

  CreateFullPolicyListing(&CurrentPolicyPair, POLICY_FILES_TO_BE_PROCESSED, POLICY_FILES_TO_BE_PROCESSED);

  return 0;
}

Ответы [ 3 ]

1 голос
/ 25 апреля 2010

Проблема в прототипе функции:

...
void SPFCreateIndividualPolicyListing(PolicyPair *IndividualPolicyPairtoCreate )
{
...

Функция получает значение указателя NULL, устанавливает его в допустимое местоположение с помощью malloc, но никоим образом не возвращает его вызывающей функции.Это должно быть

...
void SPFCreateIndividualPolicyListing(PolicyPair **IndividualPolicyPairtoCreate )
{
*IndividualPolicyPairtoCreate = malloc (...);
...
0 голосов
/ 25 апреля 2010

Поскольку я не могу прочитать ваш код с его чрезмерно длинными именами переменных и функций, я переписал нарушающую функцию следующим образом.Итак, мое первое предложение: используйте более короткие имена переменных.

void create_policies(SPFPolicyPair **policies, char *name, char *newname) {
    int i;
    for(i = 0; i < MaxNumberFileTypes; i++) {
        create_policy(policies[i]);
        strncpy((*policies)[i].IndividualFile, POLICY_FILES_TO_BE_PROCESSED, SPF_POLICY_NAME_SIZE);

    }
}

Есть несколько проблем с этим кодом.

Во-первых, как уже отмечали другие, create_policy(policies[i]) не может изменить значение policies[i], поскольку C чисто передается по значению.Запишите его как

polices[i] = create_policy();

и измените create_policy, чтобы он возвращал адрес пары политик, которую он выделяет.

Во-вторых, (*policies)[i].IndividualFile неверно .Это должно быть

(*policies[i]).IndividualFile

или даже лучше

policies[i]->IndividualFile.

В-третьих, вы не используете name или newname.

Проблема (1) и (2) приведет к ошибкам сегмента.Проблема (3) указывает либо на то, что вы пытались сократить этот код, чтобы понять segfault, либо на то, что вы не совсем точно знаете, что должна делать эта функция.


Остальная часть этого постаобъясняет вторую ошибку и ее исправление более подробно.

Вы правильно передали policies как указатель на первый элемент массива SPFPolicyPair * s.Итак, очень приблизительно

policies --> [ ptr0 | ptr1 | ptr2 | ... ]

Каждое значение ptri равно SPFPolicyPair *.Существует два способа интерпретации такого значения: (a) база массива SPFPolicyPair объектов или (b) указатель на один такой объект.Самому языку неважно, какую интерпретацию вы используете, но в вашем случае, глядя на то, как вы инициализировали массив policies, это ясно случай (b).

Итак, как выполняется оценка((*policies)[i]).IndividualFile идти не так?

  • *policies возвращает ptr0 из приведенной выше диаграммы.
  • Это значение теперь подписывается как ptr0[i].

Первым признаком проблемы является то, что вы когда-либо используете policies[0], а затем обрабатываете это значение, ptr0, как указатель на первый элемент массива объектов пары полноразмерных политик, например,

ptr0 -> [ ppair0 | ppair1 | ppair2 | ... ]

Это массив, который вы индексируете.За исключением того, что ptr0 не указывает на последовательность объектов пары политик, он указывает ровно на один такой объект.Итак, как только i больше нуля, вы перестаете ссылаться на неопределенную память.

Пересмотренное выражение policies[i]->IndividualFile работает следующим образом:

  • policies[i] эквивалентно *(policies + i) и возвращает одно из ptr0, ptr1 и т. д.
  • ptri->IndividualFile эквивалентно (*ptri).IndividualFile и возвращает базовый адрес имени файла для i th политика пары.
0 голосов
/ 25 апреля 2010
void SPFCreateIndividualPolicyListing(PolicyPair *IndividualPolicyPairtoCreate )
{
  IndividualPolicyPairtoCreate = (PolicyPair *) malloc(sizeof(PolicyPair));

Это просто присваивается локальной переменной IndividualPolicyPairtoCreate - C передается по значению, а не по ссылке. Вы теряете память, и вызывающая сторона не увидит никаких изменений в структуре, которую вы передаете.

Измените эту функцию, например, вернуть вновь выделенную память вместо

 CreateIndividualPolicyListing((CurrentPolicyPair[i]));

До

CurrentPolicyPair[i] = CreateIndividualPolicyListing();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...