The significant problem is that although storage is always allocated (with malloc() ) for the results you are trying to return as myfoo and mybar , pointers to these distributions do not actually return to main() . As a result, a later call to printf() will most likely reset the kernel.
The solution is to declare the arguments as a ponter for the char pointer and pass the addresses from myfoo and mybar to fn . Something like this (untested) should do the trick:
void fn(char *baz, char **foo, char **bar) { char *pch; pch = strtok (baz, ":"); *foo = malloc(strlen(pch)+1); strcpy(*foo, pch); pch = strtok (NULL, ":"); *bar = malloc(strlen(pch)+1); strcpy(*bar, pch); return; } int main(void) { char mybaz[] = "hello:world"; char *myfoo, *mybar; fn(mybaz, &myfoo, &mybar); fprintf(stderr, "%s %s", myfoo, mybar); free(myfoo); free(mybar); }
Remember to free each highlighted line later, otherwise you will create memory leaks.
To make both malloc () and strcpy () in one call, it would be better to use strdup() , as it also remembers to allocate space for the ending NUL that you left outside your code, as written. *foo = strdup(pch) much clearer and easier to maintain this alternative. Since strdup() is POSIX, not ANSI C, you may need to implement it yourself, but the effort will be well paid out as a result of clarity for such use.
Another traditional way to return a string from function C is for the caller to allocate storage and indicate its function address. This is the method used, for example, by sprintf() . He suffers from the problem that there is no way to make such a call site completely safe for buffer overflow errors caused by the called function, assuming that more space has been allocated than is actually available. The traditional repair of this problem is to require that the buffer length argument also be passed, and carefully check both the actual distribution and the length declared on the call site in the code review.
Edit:
The actual segfault that you get will most likely be inside strtok() , not printf() , because your sample, as it is written, is trying to pass a string constant to strtok() , which should be able to modify the string. This is officially Undefined Behavior.
The fix for this problem is to make sure that bybaz declared as an initialized array, and not as a pointer to a char . The initialized array will be in writable memory, and the string constant is likely to be in read-only memory. In many cases, string constants are stored in the same part of memory that is used to store the executable code itself, and modern systems try to make it difficult to modify a program with its own code.
In the embedded systems that I work on for a living, the code will most likely be stored in some kind of ROM and cannot be physically modified.