Why the second strcpy() in my code causes stop working? - c

I wrote this C code:
#include<stdio.h>
#include<string.h>
int main()
{
char *i, *p, *p1="Hello";
strcpy(p,p1); //The first strcpy works.
printf("%s\n", p); //show copy successful
printf("Please hit a key to continue....\n");
getchar();
strcpy(i,p); //The second strcpy causes stop working problem. Why?
printf("%s\n", i);
return 0;
}
Can anyone tell me why the second strcpy doesn't work?

I would say you were lucky the first strcpy worked in the first place!
You basically declared a POINTER to a char, nothing else.
What you need in order for strcpy to work correctly is make sure you have an array of char large enough to fit your copy in. In other words, allocate some memory first for your pointer, or use an array...

you need to allocate memory for the chars. you could e.g. do it like this:
char* p1 = "Hello";
char* i = (char*)malloc(sizeof(char) * 6);
char* p = (char*)malloc(sizeof(char) * 6);
please don't miss a free afterwards (before return):
free(p);
free(i);
Moreover an additional include is needed to use malloc and free:
#include<stdlib.h>
Your complete sample should be looking like this:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char* p1 = "Hello";
char* i = (char*)malloc(sizeof(char) * 6);
char* p = (char*)malloc(sizeof(char) * 6);
// 1st copy
strcpy(p,p1);
printf("1st copy: %s\n", p);
// 2nd copy
strcpy(i,p);
printf("2nd copy: %s\n", i);
getchar();
// free prior allocated memory
free(p);
free(i);
return 0;
}

The problem is that strcpy won't allocate memory for your string hence it will most likely crash if you haven't done so. I'd say its by chance the first instance works.
You're lucky the program only gives you a segmentation fault. You can either allocate memory using malloc or calloc or you use the function strdup to allocate memory for you.
char *i, *p, *p1="Hello";
p = strdup(p1);
printf("%s\n", p); //show copy successful
printf("Please hit a key to continue....\n");
getchar();
i = strdup(p);
printf("%s\n", i);
free(p);
free(i);
Don't forget to free the memory afterwards!

Related

How can I implement a function to concatenate to a char* and not char array?

How can I implement a function that will concatenate something to a char* (not char array)?
Example of what I want:
#include <stdio.h>
#include <string.h>
int main() {
char* current_line;
char temp[1];
sprintf(temp, "%c", 'A');
// This causes a seg fault. I of course don't want that, so how do I get this to work properly?
strcat(current_line, temp);
return 0;
}
How can I fix this to work properly (and please, tell me if I need to add anything to my question or point me in the right direction because I couldn't find anything)?
Edit: I made this but it seg faults
char* charpointercat(char* mystr, char* toconcat) {
char ret[strlen(mystr) + 1];
for(int i = 0; mystr[i] != '\0'; i++) {
ret[i] = mystr[i];
}
return ret;
}
You have 3 problems:
You do not allocate memory for current_line at all!
You do not allocate enough memory for temp.
You return a pointer to a local variable from charpointercat.
The first one should be obvious, and was explained in comments:
char *current_line only holds a pointer to some bytes, but you need to allocate actual bytes if you want to store something with a function like stracat.
For the secoond one, note that sprintf(temp, "%c", 'A'); needs at least char temp[2] as it will use one byte for the "A", and one byte for terminating null character.
Since sprintf does not know how big temp is, it writes beyond it and that is how you get the segfault.
As for your charpointercat once the function exits, ret no longer exists.
To be more precise:
An array in C is represented by a pointer (a memory address) of its first item (cell).
So, the line return ret; does not return a copy of all the bytes in ret but only a pointer to the first byte.
But that memory address is only valid inside charpointercat function.
Once you try to use it outside, it is "undefined behavior", so anything can happen, including segfault.
There are two ways to fix this:
Learn how to use malloc and allocate memory on the heap.
Pass in a third array to the function so it can store the result there (same way you do with sprintf).
From the first code you posted it seems like you want to concatenate a char to the end of a string... This code will return a new string that consists of the first one followed by the second, it wont change the parameter.
char* charpointercat(char* mystr, char toconcat) {
char *ret = (char*) malloc(sizeof(char)*(strlen(mystr) + 2));
int i;
for(i = 0; mystr[i] != '\0'; i++) {
ret[i] = mystr[i];
}
ret[i] = toconcat;
ret[i + 1] = '\0';
return ret;
}
This should work:
char* charpointercat(char* mystr, char* toconcat) {
size_t l1,l2;
//Get lengths of strings
l1=strlen(mystr);
l2=strlen(toconcat);
//Allocate enough memory for both
char * ret=malloc(l1+l2+1);
strcpy(ret,mystr);
strcat(ret,toconcat);
//Add null terminator
ret[l1+l2]='\0';
return ret;
}
int main(){
char * p=charpointercat("Hello","World");
printf("%s",p);
//Free the memory
free(p);
}

Mallocing char* with same length as another char* causes it become a copy?

I am currently trying to write a simple C program that creates a struct with a char* field and assigns it to have the same value as argv[1]. I then want to create another char* with the same length as argv[1], but for some reason the data inside already contains the same value as argv[1]. Here is my code so far:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
struct example{
char *str;
};
struct example* create(char *s){
struct example *p = (struct example*)malloc(sizeof(struct example));
char * copy = (char*)malloc(strlen(s));
strcpy(copy, s);
p->str = copy;
free(copy);
return p;
}
void new_char(struct example * t){
printf("original: %s\n", t->str);
char *w = (char *)malloc(strlen(t->str));
printf("why is this a copy? %s\n", w);
free(w);
}
void clean(struct example *t){
free(t);
}
int main(int argc, char **argv){
struct example * p = create(argv[1]);
new_char(p);
clean(p);
return 0;
}
Then when I compile and run this program using GCC 6.1, I get this out put
> gcc -Wall -g -o test test.c
> ./test "test value here"
> original: test value here
> why is this a copy? test value here
this code is wrong
struct example* create(char *s){
struct example *p = (struct example*)malloc(sizeof(struct example));
char * copy = (char*)malloc(strlen(s));
strcpy(copy, s);
p->str = copy;
free(copy);
return p;
}
first you need to allocate strlen + 1
Second you cannot free 'copy' here, p->str points at it, you now have a dangling pointer. To copy and malloc use strdup http://linux.die.net/man/3/strdup
struct example* create(char *s){
struct example *p = (struct example*)malloc(sizeof(struct example));
p->str = strdup(s);
return p;
}
The reason you got the same string is because you released your string back to the heap and then got it back again when you called malloc, this is purely luck, another time you might crash, get garbage,...
Look at this lines:
char * copy = (char*)malloc(strlen(s));
...
p->str = copy;
free(copy);
return p;
You alloc a block of memory, initialize it, store a pointer to it in your structure, and then free it! From that free() on, the p->str pointer points to freed memory, that is memory that must not be used.
What happens next? You do another:
char *w = (char *)malloc(strlen(t->str));
which, by chance, gets get memory just freed from the previous code, and since malloc() does not initialize the returned memory in any way, it happens to have the same string you just used.
What you see is actually garbage (uninitialized memory) that just happens to take the shape of a recent used text.
Summing up, your code has three problems:
You free the string you are returning in create()
You do not free the string in clean() before freeing the struct.
You try to print an uninitialized chunk of memory and wonder what the garbage means.
Hrre is the problem:
char * copy = (char*)malloc(strlen(s));
strcpy(copy, s);
p->str = copy;
free(copy);
You allocated a copy of original string and immediately free it.
char *w = (char *)malloc(strlen(t->str));
This line reuses previously freed memory and that's why you get the same content - the pointer is the same.
Note this happens in very simple scenarios and is specific to c library you use.
malloc doesn't initialize the memory it allocates. The second call to malloc happened to assign the same block of memory the first call to malloc has allocated (seeing as it had become unallocated when you called free). You cannot count on this.
Errors:
You need to allocate space for the NUL too. malloc(strlen(s)) should be malloc(strlen(s)+1).
You may not access unallocated memory, as you when you print t->str and when you try to find its length. You probably didn't mean to deallocate it. free(copy); should be moved to clean as free(t->str);.
Casting the value returned by malloc is necessary in C++, but is needless in C.
Tips:
strdup is a convenient shortcut for strlen+malloc+strcpy.
If you write
typedef struct { ... } example;
instead of
struct example { ... };
you can use example instead of struct example.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
typedef struct {
char *str;
} example;
example* create(char *s){
example *p = malloc(sizeof(example));
p->str = strdup(s);
return p;
}
void new_char(example * t){
printf("original: %s\n", t->str);
char *w = strdup(t->str);
printf("%s\n", w); // Prints uninitialized memory.
free(w);
}
void clean(example *t){
free(t->str);
free(t);
}
int main(int argc, char **argv){
example * p = create(argv[1]);
new_char(p);
clean(p);
return 0;
}

Memory Leak in Returning a Pointer and Freeing it in C

I have the following code:
char *get_packet(int cc, char *args[]){
char *packet;
packet = (char*) malloc(30 * sizeof(char));
//other code..
...
return packet;
}
int main(){
int cc = SCANS_TO_ACCUMULATE;
int args[] = {5000};
char *str_args[15];
int i = 0;
for(i; i<((sizeof(args)/sizeof(args[0]))); i++){
char buffer[10];
sprintf(buffer, "%d", args[i]);
str_args[i] = strdup(buffer);
free(buffer);
}
str_args[i] = NULL;
char *pkt;
pkt = get_packet(cc, str_args);
printf("%s\n", pkt);
free(pkt);
pkt = NULL;
getchar();
return 0;
}
However, running this causes my program to crash immediately, and after doing some inspection with Dr. Memory it appears I have a memory leak, but I can't seem to find why it's occurring. Am I not freeing the malloc'd memory correctly? Thanks in advance
Your code tries to deallocate memory of buffer which is not dynamically allocated,i.e. which is a local variable-array. This causes the crash.
Here:
char buffer[10];
...
free(buffer);
You cannot free local array, remove the call to the free. The memory will be freed up automatically when the variable gets out of scope.
Freeing the local array "buffer" is undefined, and probably horrible, behavior! You can't free something unless it was allocated with malloc() or calloc(). It's likely corrupting the heap and causing the crash.

Memory Clobbering Error

I have a small piece of code. I compiled it with -lmcheck as I am trying to debug a code where I have the same similar error.
I get this error when I run this code:
memory clobbered before allocated block
Can someone explain the reason why free(ptr) will throw me this error?
How else can I free the pointer?
Thanks.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define LEN 5
int main(int argc, char *argv[]){
char *ptr = NULL;
ptr = (char *) malloc(LEN+1);// +1 for string
strcpy(ptr, "hello");
int i = 0;
for(i = 0; i<LEN; i++)
{
printf("ptr[%d] = %c\n", i, ptr[i]);
ptr++;
}
free(ptr);
return 0;
}
You are incrementing ptr, therefore changing the address that it points to. You can't do that.
In your case, have a separate pointer, let's say char * p = ptr and do your operations with p leaving ptr intact so you can free(ptr) later.
EDIT Taking a second look at your code, I found that you are doing ptr++ when you shouldn't. You are accessing the characters in the array like ptr[i], if you mess with the ptr pointer, you are changing the base address and accessing the characters with ptr[i] can lead (and will lead) to unexpected results.
If you simply remove that line (ptr++) your code will magically work.
If you want to explore the pointer concept and try another solution, your code could look something like this:
int main(int argc, char *argv[]){
char *ptr = NULL;
char * p;
ptr = (char *) malloc(LEN+1);// +1 for string (please check for NULL)
p = ptr;
strcpy(ptr, "hello");
int i = 0;
while (*p) // note how I changed it to a while loop, C strings are NULL terminated, so this will break once we get to the end of the string. What we gain is that this will work for ANY string size.
{
printf("ptr[%d] = %c\n", i++, *p); // here i dereference the pointer, accessing its individual char
p++;
}
free(ptr);
return 0;
}
Because ptr no longer points to the base of the memory you allocated.
Also, after you increment ptr, the expression ptr[i] does not return what you might expect; and that is why the output starts with "hlo".
Find the answer in comments.
When you allocate some memory, typically, the memory management framework keep tracks of it by adding some more info (you can say Header and Footer) to the allocated memory area. When you free this memory, the same info is matched so as to detect any unwanted/invalid memory access.
int main(int argc, char *argv[]){
char *ptr = NULL;
char* temp = NULL; // Have a temp pointer.
ptr = (char *) malloc(LEN+1);// +1 for string
strcpy(ptr, "hello");
temp = ptr; // manipulate temp pointer instead of ptr itself
int i = 0;
for(i = 0; i<LEN; i++)
{
printf("ptr[%d] = %c\n", i, temp[i]);
temp++; // Why you are incrementing this? Just to print, there is no need of this.
}
free(ptr);
return 0;
}

realloc and free causes "double free or corruption"

Bear with me. I have not coded in c in 8 years and am totally baffled why my string manipulation is not working. I am writing a program that loops forever. In the loop I initialize two char pointers each is passed to a function that add text to the char pointer (array). When the functions are done I print the char pointer and free the two char pointers. However the program dies after 7 iterations with the following error message
* glibc detected * ./test: double free or corruption (fasttop): 0x0804a168 ***
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include string.h
#include stdio.h
#include stdlib.h
#include errno.h
#include time.h
char *SEPERATOR = "|";
void getEvent (char* results);
void getTimeStamp(char* timeStamp, int timeStampSize);
void stringAppend(char* str1, char* str2);
int main (int argc, char *argv[])
{
int i = 0;
while(1)
{
i++;
printf("%i", i);
char* events= realloc(NULL, 1);
events[0] = '\0';
getEvent(events);
char* timestamp= realloc(NULL, 20);
timestamp[0] = '\0';
getTimeStamp(timestamp, 20);
printf("%s", events);
printf("timestamp: %s\n", timestamp);
free(events);
free(timestamp);
}
}
void getEvent (char* results)
{
stringAppend(results, "a111111111111");
stringAppend(results, "b2222222222222");
}
void getTimeStamp(char* timeStamp, int timeStampSize)
{
struct tm *ptr;
time_t lt;
lt = time(NULL);
ptr = localtime(&lt);
int r = strftime(timeStamp, timeStampSize, "%Y-%m-%d %H:%M:%S", ptr);
}
void stringAppend(char* str1, char* str2)
{
int arrayLength = strlen(str1) + strlen(str2) + strlen(SEPERATOR) + 1;
printf("--%i--",arrayLength);
str1 = realloc(str1, arrayLength);
if (str1 != NULL)
{
strcat(str1, SEPERATOR);
strcat(str1, str2);
}
else
{
printf("UNABLE TO ALLOCATE MEMORY\n");
}
}
You are reallocating str1 but not passing the value out of your function, so the potentially changed pointer is leaked, and the old value, which has been freed by realloc, is freed again by you. This causes the "double free" warning.
The problem is that while stringAppend reallocates the pointers, only stringAppend is aware of this fact. You need to modify stringAppend to take pointer-to-pointers (char **) so that the original pointers are updated.
This line in stringAppend:
str1 = realloc(str1, arrayLength);
changes the value of a local variable in stringAppend. This local variable named str1 now points to either the reallocated memory or NULL.
Meanwhile local variables in getEvent keep the values they had before, which now usually point to freed memory.
All the comments where very helpfull. Of course it makes total sense why the error was happening. I ended up solving it by making the following changes.
For both the getEvent and stringAppend I return the char pointer.
e.g.
char* stringAppend(char* str1, char* str2)
{
int arrayLength = strlen(str1) + strlen(str2) + strlen(SEPERATOR) + 1;
printf("--%i--",arrayLength);
str1 = realloc(str1, arrayLength);
if (str1 != NULL)
{
strcat(str1, SEPERATOR);
strcat(str1, str2);
}
else
{
printf("UNABLE TO ALLOCATE MEMORY\n");
}
return str1;
}
This isn't an answer to your question (and you don't need one, since the error has been pointed out), but I do have some other comments about your code:
char* events= realloc(NULL, 1);
events[0] = '\0';
You don't test that realloc successfully allocated memory.
char* timestamp= realloc(NULL, 20);
timestamp[0] = '\0';
Same problem here. In this case, you don't need realloc at all. Since this is a fixed-size buffer, you could use just:
char timestamp[20] = "";
And don't do this:
str1 = realloc(str1, arrayLength);
because if realloc fails, you'll orphan the memory that str1 was pointing to before. Instead:
char* temp = realloc(str1, arrayLength);
if (temp != NULL)
{
str1 = temp;
...
}
Note that since you're modifying stringAppend to return the new string, you should do similar checks in the calling functions.
Also, "separator" is spelled with two As, not with two Es.

Resources