Stripped down to the actual issue:
void removeWS(char *strNoSpace, const char *strWithSpace)
{
strNoSpace = malloc(strlen(strWithSpace) + 1);
// ...
}
// ....
char* paramStrNoSpace = NULL;
char* paramStrWithSpace = "...";
removeWS(paramStrNoSpace, paramStrWithSpace);
Now strNoSpace
is a copy of paramStrNoSpace
It points to the same memory, which in this case is NULL. Then inside your function you change strNoSpace
to something, malloc()
returns. Now strNoSpace
is something different to NULL, while paramStrNoSpace
is still NULL, because strNoSpace
was a copy of that pointer.
A simple soulution could be to pass a pointer to a pointer instead:
void removeWS(char **strNoSpace, const char *strWithSpace)
{
*strNoSpace = malloc(strlen(strWithSpace) + 1);
// ...
}
// ....
char* paramStrNoSpace = NULL;
char* paramStrWithSpace = "...";
removeWS(¶mStrNoSpace, paramStrWithSpace);
Now strNoSpace
points to the exact position, where the pointer paramStrNoSpace
is stored. Whenever you modify *strNoSpace
, you actually modify paramStrNoSpace
now.
The downside of that approach is, that you will loose track of your memory allocations sooner or later, when functions just allocate and return new memory. The rule of thumb is: whoever allocates memory, is also responsible to free it. Therefore I think a better interface would expect the caller to allocate enough memory for this function:
void removeWS(char *strNoSpace, ind strNoSpaceMaxSize, const char *strWithSpace)
{
// ...
}
// ....
char* paramStrWithSpace = "...";
char* paramStrNoSpace = malloc(strlen(paramStrWithSpace) + 1);
removeWS(paramStrNoSpace, strlen(paramStrWithSpace), paramStrWithSpace);
Now removeWS()
does never change strWithSpace
. Therefore we can pass it as a simple pointer again, but we have to tell removeWS()
the size of the allocated memory block. It has to check while running and stop in case, there is not enough memory.