0

First, I write a simple program.

  1 #include <string.h>
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4
  5 int main()
  6 {
  7     char *buf = (char*)malloc(sizeof(char)*2000);
  8     char tmp[256];
  9     strcpy (tmp, "test");
 10     printf ("tmp: %s\n", tmp);
 11     strncat (buf, tmp, strlen(tmp));
 12     printf ("buf: %s\n", buf);
 13 }

The expected result is:

tmp: test
buf: test

But after I combine the code in my big project. (which use lots heap segments)

153     char *inbuf = (char*)malloc(sizeof(char)*2000);
154     char *outbuf = (char*)malloc(sizeof(char)*2000);
155     char *oldinbuf = (char*)malloc(sizeof(char)*2000);
156     char *errbuf = (char*)malloc(sizeof(char)*2000);
157     memset (inbuf, '\0', strlen(inbuf));
158     memset (oldinbuf, '\0', strlen(oldinbuf));
159     memset (errbuf, '\0', strlen(oldinbuf));

Then in the line:11, I get the error message Segmentation fault (core dumped)

Is there any possibilities that strncat result in segment fault?

Kir Chou
  • 2,980
  • 1
  • 36
  • 48
  • Because I need to concatenate the old content in `buf` and new content in `tmp`, and I checked the old content in inbuf careful (within malloc size). – Kir Chou Nov 22 '14 at 10:25
  • 1
    We don't see `buf` being initialized with any value before `strncat()` which is why you are seeing the issue. If buf had some value before `strncat` then this would have worked fine. So if this is the case you can use `strncpy()` – Gopi Nov 22 '14 at 10:31
  • Instead of `malloc + memset` you can use `calloc` [which may be faster anyway](http://stackoverflow.com/questions/2688466/why-mallocmemset-is-slower-than-calloc/). Your `memset` on lines 157-159 set the [wrong number of bytes](http://stackoverflow.com/questions/492384/how-to-find-the-sizeofa-pointer-pointing-to-an-array). Also [see here](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) for modern usage of malloc. – M.M Nov 22 '14 at 10:33
  • Your question is unclear, do you get the segfault in your test program, or in your "real code", or on bith? – M.M Nov 22 '14 at 10:37
  • @Matt Sorry, I get segment fault in my real code. The test program works fine. (I edited my code from `sizeof` to `strlen`) – Kir Chou Nov 22 '14 at 10:40
  • 1
    In the edited code the segfault will come freom using `strlen` on uninitialized memory on lines 157-159. Please edit your post; it says that you get segfault on line 11 but in fact you don't. Make sure that the code you post does actually give the problem. – M.M Nov 22 '14 at 10:42
  • Thanks. I already found the error is resulted from initialization `buf`, but to be shamed, the error doesn't come from the code I provided in my question. – Kir Chou Nov 22 '14 at 10:49

2 Answers2

6

This line has undefined behavior

strncat (buf, tmp, strlen(tmp));

because buf comes from malloc uninitialized. strncat, on the other hand, expects buf to contain a null-terminated C string.

You can fix this by setting the initial character of buf to '\0'.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

If you are going to use strcat or sttrncat then buf shall have a valid string. So write

char *buf = (char*)malloc(sizeof(char)*2000);
buf[0] = '\0';

Also if you use strncat then you always have to append the terminating zero yourself that the copying would be safe. For example

size_t n = strlen(tmp);
strncat (buf, tmp, n + 1 );
buf[n] = '\0';

Though in this particular case you could use simply strcat instead of strncat

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335