I have been using strcat
to join several strings. Everything appears to be correct, prints:
/proc/573/fd/ <- with the backslash
13 <- length
After I try to copy the "src" string with strcpy
to another string, the trailing character doesn't print in either the "dest" or the "src" strings:
/proc/573/fd <- same string prints without the backslash?
13 <- length is unchanged?
If I call strlen
the length shows it is unchanged though?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// This function counts the number of digit places in 'pid'
int pid_digit_places(int pid)
{
int n = pid;
int places = 0;
while (n)
n /= 10;
places++;
return places;
}
char *construct_path(int pid, char *dir)
{
// get count of places in pid
int places = pid_digit_places(pid);
char *pid_str = calloc(places, sizeof(char));
// create string of pid
sprintf(pid_str, "%d", pid);
char *proc = "/proc/";
size_t plen = strlen(proc);
size_t dlen = strlen(dir) + 1;
char *path = calloc(plen + dlen + places, sizeof(char));
strcat(path, proc);
strcat(path, pid_str);
strcat(path, dir);
return path;
}
void fd_walk(int pid)
{
char *fd = "/fd/";
char *fdpath = construct_path(pid, fd);
// prints "/proc/573/fd/ - as expected
printf("Before: %s\n", fdpath);
// shows a length of 13
printf("Size Before: %d\n", (int)strlen(fdpath));
char *test = calloc(strlen(fdpath) + 1, sizeof(char));
strcpy(test, fdpath);
// prints "/proc/573/fd" no trailing "/"
printf("Copied Str: %s\n", test);
//shows a length of 13 though
printf("Copied Size: %d\n", (int)strlen(test));
// prints "/proc/573/fd" no trailing "/" now
printf("After: %s\n", fdpath);
// still shows length of 13
printf("Size After: %d\n", (int)strlen(fdpath));
}
int main(void)
{
// integer to create path around
int pid = 573;
fd_walk(pid);
return 0;
}
I'm compiling on gcc-4.8.2
with -Wall
:
gcc -o src src.c -Wall
I've popped this small example into ideone.
I've made sure to add an extra space for the null-terminator
when allocating memory.
I've thought to re-examine how I'm intializing my pointers first and haven't seen anything wrong? How is the string printing as expected with printf
and then after copying it, printf
prints something different -- undefined behavior?
I have executed your exact code with no troubles. Nonetheless, I see two possible problems:
// This function counts the number of digit places in 'pid'
int pid_digit_places(int pid)
{
int n = pid;
int places = 0;
while (n) { // <-- The braces were missing here.
n /= 10;
places++;
}
return places;
}
char *construct_path(int pid, char *dir)
{
// get count of places in pid
int places = pid_digit_places(pid);
// You need "places" bytes for the digits, plus one for the zero
char *pid_str = calloc(places + 1, sizeof(char));
However, in general, I wouldn't waste time to allocate exactly the memory I needed; the extra code more than compensates in size and complexity.
Just make a guess on the largest possible value, and enforce that guess:
// avoid pid_digit_places altogether
pid_str = malloc(16);
if (pid > 999999999999L) {
// fprintf an error and abort.
// Better yet, see whether this is a limit #define'd in the OS,
// and place an appropriate compile-time # warning. Chances are
// that unless your code's trivial, running it on a system with
// such large PIDs (and therefore likely so different an arch!)
// would cause some other troube to pop up.
// With an # error in place, you save also the pid check!
}