开发者

Problem with passing array of pointers to struct among functions in C

The Code that follows segfaults on the call to strncpy and I can't see what I am doing wrong. I need another set of eyes to look it this. Essentially I am trying to alloc memory for a struct that is pointed to by an element in a array of pointers to struct.

#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 * siz开发者_Python百科eof(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;
}


Problem is in the prototype of function:

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

The function gets a NULL pointer value, sets it to a valid location by malloc but doesn't in any way return it to calling function. It should be

...
void SPFCreateIndividualPolicyListing(PolicyPair **IndividualPolicyPairtoCreate )
{
*IndividualPolicyPairtoCreate = malloc (...);
...


void SPFCreateIndividualPolicyListing(PolicyPair *IndividualPolicyPairtoCreate )
{
  IndividualPolicyPairtoCreate = (PolicyPair *) malloc(sizeof(PolicyPair));

That just assigns to the local IndividualPolicyPairtoCreate variable - C is pass by value, not pass by reference. You're leaking memory, and the caller won't see any changes to the struct you're passing in.

Change that function to e.g. return the newly allocated memory, and instead of

 CreateIndividualPolicyListing((CurrentPolicyPair[i]));

Do

CurrentPolicyPair[i] = CreateIndividualPolicyListing();


Because I can't read your code with its excessively long variable and function names, I've rewritten the offending function as follows. So, my first suggestion is: use shorter variable names.

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);

    }
}

There are multiple problems with this code.

First, as others have pointed out, create_policy(policies[i]) can not change the value of policies[i] because C is purely pass by value. Write it as

polices[i] = create_policy();

and change create_policy to return the address of policy pair it allocates.

Second, (*policies)[i].IndividualFile is wrong. It should be

(*policies[i]).IndividualFile

or even better

policies[i]->IndividualFile.

Third, you don't use name or newname.

Problem (1) and (2) will both lead to segfaults. Problem (3) indicates either that you've been trying to strip this code down to understand the segfault, or that you're not sure exactly what this function should do.


The rest of this post explains the second bug and its fix in more detail.

You have correctly passed in policies as a pointer to the first element of an array of SPFPolicyPair *s. So, very roughly

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

Each ptri value is a SPFPolicyPair *. There are two ways to interpret such a value: (a) the base of an array of SPFPolicyPair objects, or (b) a pointer to a single such object. The language itself doesn't care which interpretation your using, but in your case, by looking at how you've initialized the policies array, it's clearly case (b).

So, how does the evaluation ((*policies)[i]).IndividualFile go wrong?

  • *policies returns ptr0 from the diagram above.
  • That value is now subscripted, as ptr0[i].

The first indication of trouble is that you're only ever using policies[0], and then treating this value, ptr0, as a pointer to the first element of an array of full-sized policy pair objects, eg,

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

This is the array you're indexing. Except that ptr0 does not point to a sequence of policy pair objects, it points to exactly one such object. So, as soon as i is greater than zero, you're off referencing undefined memory.

The revised expression, policies[i]->IndividualFile, works like this:

  • policies[i] is equivalent to *(policies + i), and returns one of ptr0, ptr1, etc.
  • ptri->IndividualFile is equivalent to (*ptri).IndividualFile, and returns the base address of the file name for the ith policy pair.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜