DR.
DR.

Reputation: 593

Does using calloc inside function, change the pointer passed as function argument

I do not understand why the second printf loop outputs different data than the first printf loop that was done inside the function scope. Can it be that the pointer is changed somehow inside the function so that when it returns it returns a different value?

Output:

First printf inside function:
Parts TMP|01245
Parts X|40001
Parts Y|98760

Second printf outside function, in main:
It returns jiberish and not the same as when printing inside the function. I tried to fprintf so that I can quickly paste the results in here ,but then I received an uninformative call stack error.

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

void ProtocolParse_Start(int *numParts,char **parts, char *str, const char* partsDelim )
{
  int partCount = strChrCount(str,'~');
  *numParts = partCount;

  parts = (char**)calloc(partCount,sizeof(char));
  char *tempPart;


  tempPart = strtok (str,partsDelim);
  parts[0] = (char*)calloc(strlen(tempPart),sizeof(char));
  strcpy(parts[0],tempPart);


  int i =1;
  for(; i < partCount; i++)
  {
      tempPart = strtok (NULL, partsDelim);
      parts[i] = (char*)calloc(strlen(tempPart),sizeof(char));
      strcpy(parts[i],tempPart);
  }

   i =0;
  for(; i < partCount; i++)
  {
      printf ("%Parts %s\n",parts[i]);
  }

}

void ProtocolParse_End(int numParts,char **parts)
{
    int i = 0;
    for (; i < numParts; i++)
        free (parts[i]);

    free (parts);
}


int main()
{
    char proto[32] = "TMP|01245~X|40001~Y|98760~";

    char **parts;
    int numParts;
    ProtocolParse_Start(&numParts, parts,proto,"~");


     int i =0;
     for(; i < numParts; i++)
     {
          printf ("%Parts %s\n",parts[i]);
     }

    ProtocolParse_End(numParts,parts);

    return 0;
}

Can anyone please shed some light onto my problem. Because I am not sure what I'm doing wrong ??

Upvotes: 1

Views: 1598

Answers (2)

vlad_tepesch
vlad_tepesch

Reputation: 6883

There are different mistakes:

When you pass a parameter to a function it is always copied. You gave a char **parts and it is copied.

Inside the function you overwrite the copied input with the new address of the calloced pointer.

Consider an easier example:

void doSomething(int a){
  a=5;
}
///...
int b = 6;
doSomething(b);

When you call doSomething(b), your b is not changed. If you want it to be changed, you have to pass a pointer to b.

void doSomething(int* a){
  *a=5;
}
///...
int b = 6;
doSomething(&b);

The same is with your char*array.

You have char** partsin your main, that you want to be set to the allocated array. so you have to pass its pointer. and write the obtained address to the dereferenced pointer.

The other big mistake is, that you gibe the wrong soze to the first calloc. It should be sizeof(char*).

Your routine should start like this:

void ProtocolParse_Start(int *numParts,char ***parts, char *str, const char* partsDelim )
{
  int partCount = strChrCount(str,'~');
  *numParts = partCount;

  *parts = (char**)calloc(partCount,sizeof(char*));
  char *tempPart;
  //...

(all further accesses to parts in the function have to dereference parts)

and the call have to look like:

ProtocolParse_Start(&numParts, &parts,proto,"~");

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726809

The assignment of parts inside the function has no effect on the char **parts from main. In order to modify it, you need to pass a pointer to parts, and add an extra level of indirection (yes, you'd get three asterisks now).

The code that partitions the data to strings is incorrect, too: you need to allocate an array of character pointers, and then copy each token into that array individually.

void ProtocolParse_Start(int *numParts, char ***parts, char *str, const char* partsDelim )
{
  int partCount = strChrCount(str,'~');
  *numParts = partCount;

  *parts = malloc(partCount * sizeof(char*));

  char *tempPart;
  tempPart = strtok (str,partsDelim);
  (*parts)[0] = malloc(strlen(tempPart)+1);
  strcpy((*parts)[0], tempPart);

  int i =1;
  for(; i < partCount; i++)
  {
      tempPart = strtok (NULL, partsDelim);
      (*parts)[i] = malloc(strlen(tempPart)+1);
      strcpy((*parts)[i],tempPart);
  }

  i =0;
  for(; i < partCount; i++) {
      printf ("%Parts %s\n", (*parts)[i]);
  }

}

I made three changes to your code:

  • Replaced calloc with malloc: you initialize every element anyway, so there is no reason to zero-fill the block
  • Removed casts in front of malloc - this is not necessary in C
  • Added one to strlen(tempPart) - you need this for null terminated strings.

Upvotes: 2

Related Questions