views:

1687

answers:

5

My program is like this (main.c):

#include <stdlib.h>
#include <stdio.h>
void main(){
  char *first="hello ";
  char *second="world!";
  char *seq=(char *)malloc((strlen(first)+1)*sizeof(char));
  strcat(strcpy(seq,first),second);
  printf("%s\n",seq);
  free(seq);
}

and I debug with the tool valgrind, it said that($:valgrind --tool=memcheck --leak-check=full --track-origins=yes ./main):

==5118== Memcheck, a memory error detector.
==5118== Copyright (C) 2002-2008, and GNU GPL'd, by Julian Seward et al.
==5118== Using LibVEX rev 1884, a library for dynamic binary translation.
==5118== Copyright (C) 2004-2008, and GNU GPL'd, by OpenWorks LLP.
==5118== Using valgrind-3.4.1, a dynamic binary instrumentation framework.
==5118== Copyright (C) 2000-2008, and GNU GPL'd, by Julian Seward et al.
==5118== For more details, rerun with: -v
==5118== 
==5118== Invalid write of size 1
==5118==    at 0x402575B: strcat (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==5118==    by 0x80484EB: main (main.c:7)
==5118==  Address 0x418a02f is 0 bytes after a block of size 7 alloc'd
==5118==    at 0x402522D: malloc (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==5118==    by 0x80484C3: main (main.c:6)
==5118== 
==5118== Invalid write of size 1
==5118==    at 0x4025777: strcat (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==5118==    by 0x80484EB: main (main.c:7)
==5118==  Address 0x418a034 is 5 bytes after a block of size 7 alloc'd
==5118==    at 0x402522D: malloc (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==5118==    by 0x80484C3: main (main.c:6)
==5118== 
==5118== Invalid read of size 1
==5118==    at 0x4025963: strlen (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==5118==    by 0x40A0FA4: puts (in /lib/libc-2.10.1.so)
==5118==    by 0x80484F7: main (main.c:8)
==5118==  Address 0x418a02f is 0 bytes after a block of size 7 alloc'd
==5118==    at 0x402522D: malloc (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==5118==    by 0x80484C3: main (main.c:6)
==5118== 
==5118== Invalid read of size 1
==5118==    at 0x40ACEFE: _IO_default_xsputn (in /lib/libc-2.10.1.so)
==5118==    by 0x40AA3D0: _IO_file_xsputn@@GLIBC_2.1 (in /lib/libc-2.10.1.so)
==5118==    by 0x40A1020: puts (in /lib/libc-2.10.1.so)
==5118==    by 0x80484F7: main (main.c:8)
==5118==  Address 0x418a02f is 0 bytes after a block of size 7 alloc'd
==5118==    at 0x402522D: malloc (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==5118==    by 0x80484C3: main (main.c:6)
hello world!
==5118== 
==5118== ERROR SUMMARY: 17 errors from 4 contexts (suppressed: 13 from 1)
==5118== malloc/free: in use at exit: 7 bytes in 1 blocks.
==5118== malloc/free: 1 allocs, 0 frees, 7 bytes allocated.
==5118== For counts of detected errors, rerun with: -v
==5118== searching for pointers to 1 not-freed blocks.
==5118== checked 47,492 bytes.
==5118== 
==5118== 
==5118== 7 bytes in 1 blocks are definitely lost in loss record 1 of 1
==5118==    at 0x402522D: malloc (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==5118==    by 0x80484C3: main (main.c:6)
==5118== 
==5118== LEAK SUMMARY:
==5118==    definitely lost: 7 bytes in 1 blocks.
==5118==      possibly lost: 0 bytes in 0 blocks.
==5118==    still reachable: 0 bytes in 0 blocks.
==5118==         suppressed: 0 bytes in 0 blocks.

Who can tell me why and how to fix it.

+3  A: 

You are only allocating enough space for first in seq.

Anzurio
+8  A: 
 char *seq=(char *)malloc((strlen(first)+1)*sizeof(char));

You are allocating memory for a string the size of just 'first'.

  strcat(strcpy(seq,first),second);

And then you try to fit both first and second in it. That's never going to work. strcat doesn't create more memory, you need to have included that in the malloc.

There is no need to cast the result of malloc in pure C.

It is also not necessary to do sizeof(char), as that is guaranteed to be 1. Some like to have it there anyway to be explict about the type in case it changes, some consider it clutter.

Chris Arguin
there's no need to cast the return value of `malloc()` in C; also, `sizeof(char)` is always `1`
Christoph
+1  A: 

seq is only (strlen(first)+1)*sizeof(char) long, not enough to hold the concatenated string first + second.

Falaina
A: 

I could see that the line :

strcat(strcpy(seq,first),second);

is not wrongly framed. The reason is, you are doing a string concatenation , where you are not giving a proper source. It will work fine, if you seggregate the above syntax into 2 lines.

strcpy(seq,first); strcat(seq,second);

This is because, when you are doing a string copy, it will copy the string from "first" to "seq". Now, for string concatenation, since it could not find the proper source [ remember that you didnot specifically mentioned that the source is "seq" ], it is giving a invalid write memory leak problem.

Hope this clarifies your question. Please revert, if any further info is required, for the same.

Roopesh Majeti
Also, as mentioned above, by others, you need to allocate the proper memory for seq, to store for "second" also.
Roopesh Majeti
`strcpy()` returns its first argument, so `strcat(strcpy(seq, first), scond)` is equivalent to `strcpy(seq, fiest); strcat(seq, second);`.
Adam Rosenfield
+1  A: 

Where's the corresponding free() for the malloc()?

Justicle
haha, I lost it, I just want to demonstrate the error of strcpy and strcat. Of course, I should add free(seq); thank you all the same.
Charlie Epps
the memory is implicitly free'd by the OS after `main()` returns
Christoph
Wow - why do I ever bother calling `free()` then? :-)
Justicle
It's worth calling free() at a mid-point in the execution, where the application may need to allocate more memory in the future. Not at the end of main(), though.
caf
Its worth it just to have a clean output from valgrind. You wouldn't leave compiler warnings in your code would you?
Justicle
@caf Tools like valgrind expect you to free all your memory, or they will report it as a leak. It's just good practice anyway; one day you'll restructure your code and forget all those frees.
Chris Arguin
@Chis +1 For mentioning good practice.
Helper Method