3

I wrote this simple C program and couldn't quite figure out this bizarre behavior of strcat

long sum(long col, char* path, char* path2){

    printf("%s\n",path2);
    strcat(path,".endlines");
    printf("%s\n",path2);
    return 0;
}

int main(int argc, char* argv[]) {
    int n=atoi(argv[1]);
    sum(n,argv[2],argv[3]);
    exit(EXIT_SUCCESS);
}

strcat is applied on path, but path2 is eventually modified as well. I would very much appreciate if someone let me know what was happening :) thanks

Run

./program 3 example/mountdir/location2.csv example/rootdir/location2.csv

output:

example/rootdir/location2.csv

endlines

NQC
  • 33
  • 5

2 Answers2

6

You are overrunning a buffer. The original argv[2] and argv[3] are very likely consecutive in memory. When you strcat onto the end of argv[2], it is writing onto the memory argv[3] points at. You need to allocate new buffers to hold the larger strings you are trying to make.

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
  • 1
    `strncat` isn't helpful here, although there are some situations where it is. – Steve Jessop Aug 16 '11 at 12:51
  • Does C have any mechanism to prevent this? I mean... for example I malloc 2 char* and as you say there's a chance they are somehow allocated next to each other. Since I don't know what happened, am I supposed to strcpy to another buffer every time strcat is needed, just to be sure? That's just too weird, isn't it? – NQC Aug 16 '11 at 12:54
  • It is your responsibility to know how large your buffers are. strncat is good because you can limit the number of characters concatenated so you do not overflow your buffer. – Joe Aug 16 '11 at 12:58
  • @NQC, yes, you're correct. Always allocate new space for it. And no, it's not weird, it's the way computers work. And C let us tell the computer what to do in details. – sidyll Aug 16 '11 at 12:58
3

First, you cannot write to argv[2]. (doing so produces behavior that is either implementation dependent or undefined. The distinction is unimportant: don't do it).

Second; where is the confusion? You probably have memory layed out with argv[2] immediately following argv[1], so it looks like "example/mountdir/location2.csv\0example/rootdir/location2.csv". argv[ 2 ] (path) points to the first 'e', and path2 points to the 'e' following the null byte. When you strcat to path, you are writing data starting at the \0, so the \0 gets replaced by '.', the 'e' gets replaced by the 'e' of endlines, etc, and now path2 points to the second character of the string '.endlines', so you print it and get output "endlines".

William Pursell
  • 204,365
  • 48
  • 270
  • 300